mirror of
https://github.com/honojs/hono.git
synced 2024-11-21 10:08:58 +01:00
fix(helper/websocket): allow custom events to be passed to generics (#3616)
* fix(helper/websocket): allow custom events to be passed to generics * chore: disable any * add tests * patch * test patch
This commit is contained in:
parent
ae6165b994
commit
6b9fb24874
@ -21,14 +21,13 @@ describe('upgradeWebSocket middleware', () => {
|
||||
app.get(
|
||||
'/ws',
|
||||
upgradeWebSocket(() => ({
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
onMessage(evt, ws) {
|
||||
resolve(evt.data)
|
||||
resolve([evt.data, ws.readyState || 1])
|
||||
},
|
||||
}))
|
||||
)
|
||||
)
|
||||
it('Should receive message is valid', async () => {
|
||||
it('Should receive message and readyState is valid', async () => {
|
||||
const sendingData = Math.random().toString()
|
||||
await app.request('/ws', {
|
||||
headers: {
|
||||
@ -41,7 +40,7 @@ describe('upgradeWebSocket middleware', () => {
|
||||
})
|
||||
)
|
||||
|
||||
expect(sendingData).toBe(await wsPromise)
|
||||
expect([sendingData, 1]).toStrictEqual(await wsPromise)
|
||||
})
|
||||
it('Should call next() when header does not have upgrade', async () => {
|
||||
const next = vi.fn()
|
||||
|
@ -1,51 +1,53 @@
|
||||
import { WSContext, defineWebSocketHelper } from '../../helper/websocket'
|
||||
import type { UpgradeWebSocket, WSReadyState } from '../../helper/websocket'
|
||||
import type { UpgradeWebSocket, WSEvents, WSReadyState } from '../../helper/websocket'
|
||||
|
||||
// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332
|
||||
export const upgradeWebSocket: UpgradeWebSocket<WebSocket> = defineWebSocketHelper(
|
||||
async (c, events) => {
|
||||
const upgradeHeader = c.req.header('Upgrade')
|
||||
if (upgradeHeader !== 'websocket') {
|
||||
return
|
||||
}
|
||||
|
||||
// @ts-expect-error WebSocketPair is not typed
|
||||
const webSocketPair = new WebSocketPair()
|
||||
const client: WebSocket = webSocketPair[0]
|
||||
const server: WebSocket = webSocketPair[1]
|
||||
|
||||
const wsContext = new WSContext<WebSocket>({
|
||||
close: (code, reason) => server.close(code, reason),
|
||||
get protocol() {
|
||||
return server.protocol
|
||||
},
|
||||
raw: server,
|
||||
get readyState() {
|
||||
return server.readyState as WSReadyState
|
||||
},
|
||||
url: server.url ? new URL(server.url) : null,
|
||||
send: (source) => server.send(source),
|
||||
})
|
||||
|
||||
if (events.onOpen) {
|
||||
server.addEventListener('open', (evt: Event) => events.onOpen?.(evt, wsContext))
|
||||
}
|
||||
if (events.onClose) {
|
||||
server.addEventListener('close', (evt: CloseEvent) => events.onClose?.(evt, wsContext))
|
||||
}
|
||||
if (events.onMessage) {
|
||||
server.addEventListener('message', (evt: MessageEvent) => events.onMessage?.(evt, wsContext))
|
||||
}
|
||||
if (events.onError) {
|
||||
server.addEventListener('error', (evt: Event) => events.onError?.(evt, wsContext))
|
||||
}
|
||||
|
||||
// @ts-expect-error - server.accept is not typed
|
||||
server.accept?.()
|
||||
return new Response(null, {
|
||||
status: 101,
|
||||
// @ts-expect-error - webSocket is not typed
|
||||
webSocket: client,
|
||||
})
|
||||
export const upgradeWebSocket: UpgradeWebSocket<
|
||||
WebSocket,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
any,
|
||||
Omit<WSEvents<WebSocket>, 'onOpen'>
|
||||
> = defineWebSocketHelper(async (c, events) => {
|
||||
const upgradeHeader = c.req.header('Upgrade')
|
||||
if (upgradeHeader !== 'websocket') {
|
||||
return
|
||||
}
|
||||
)
|
||||
|
||||
// @ts-expect-error WebSocketPair is not typed
|
||||
const webSocketPair = new WebSocketPair()
|
||||
const client: WebSocket = webSocketPair[0]
|
||||
const server: WebSocket = webSocketPair[1]
|
||||
|
||||
const wsContext = new WSContext<WebSocket>({
|
||||
close: (code, reason) => server.close(code, reason),
|
||||
get protocol() {
|
||||
return server.protocol
|
||||
},
|
||||
raw: server,
|
||||
get readyState() {
|
||||
return server.readyState as WSReadyState
|
||||
},
|
||||
url: server.url ? new URL(server.url) : null,
|
||||
send: (source) => server.send(source),
|
||||
})
|
||||
|
||||
// note: cloudflare workers doesn't support 'open' event
|
||||
|
||||
if (events.onClose) {
|
||||
server.addEventListener('close', (evt: CloseEvent) => events.onClose?.(evt, wsContext))
|
||||
}
|
||||
if (events.onMessage) {
|
||||
server.addEventListener('message', (evt: MessageEvent) => events.onMessage?.(evt, wsContext))
|
||||
}
|
||||
if (events.onError) {
|
||||
server.addEventListener('error', (evt: Event) => events.onError?.(evt, wsContext))
|
||||
}
|
||||
|
||||
// @ts-expect-error - server.accept is not typed
|
||||
server.accept?.()
|
||||
return new Response(null, {
|
||||
status: 101,
|
||||
// @ts-expect-error - webSocket is not typed
|
||||
webSocket: client,
|
||||
})
|
||||
})
|
||||
|
@ -20,8 +20,8 @@ export interface WSEvents<T = unknown> {
|
||||
/**
|
||||
* Upgrade WebSocket Type
|
||||
*/
|
||||
export type UpgradeWebSocket<T = unknown, U = any> = (
|
||||
createEvents: (c: Context) => WSEvents<T> | Promise<WSEvents<T>>,
|
||||
export type UpgradeWebSocket<T = unknown, U = any, _WSEvents = WSEvents<T>> = (
|
||||
createEvents: (c: Context) => _WSEvents | Promise<_WSEvents>,
|
||||
options?: U
|
||||
) => MiddlewareHandler<
|
||||
any,
|
||||
|
Loading…
Reference in New Issue
Block a user