diff --git a/.changeset/light-goats-teach.md b/.changeset/light-goats-teach.md new file mode 100644 index 00000000..bb4933eb --- /dev/null +++ b/.changeset/light-goats-teach.md @@ -0,0 +1,5 @@ +--- +'@hono/node-ws': patch +--- + +Add a `CloseEvent` class to avoid exception "CloseEvent is not defined" diff --git a/packages/node-ws/src/events.ts b/packages/node-ws/src/events.ts new file mode 100644 index 00000000..539762b2 --- /dev/null +++ b/packages/node-ws/src/events.ts @@ -0,0 +1,32 @@ +interface CloseEventInit extends EventInit { + code?: number; + reason?: string; + wasClean?: boolean; +} + +/** + * @link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent + */ +export const CloseEvent = globalThis.CloseEvent ?? class extends Event { + #eventInitDict + + constructor( + type: string, + eventInitDict: CloseEventInit = {} + ) { + super(type, eventInitDict) + this.#eventInitDict = eventInitDict + } + + get wasClean(): boolean { + return this.#eventInitDict.wasClean ?? false + } + + get code(): number { + return this.#eventInitDict.code ?? 0 + } + + get reason(): string { + return this.#eventInitDict.reason ?? '' + } +} diff --git a/packages/node-ws/src/index.test.ts b/packages/node-ws/src/index.test.ts index 5ab99312..9cb12cb0 100644 --- a/packages/node-ws/src/index.test.ts +++ b/packages/node-ws/src/index.test.ts @@ -13,6 +13,7 @@ describe('WebSocket helper', () => { beforeEach(async () => { app = new Hono() + ;({ injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app })) server = await new Promise((resolve) => { @@ -108,6 +109,21 @@ describe('WebSocket helper', () => { connections.forEach((ws) => ws.close()) }) + it('CloseEvent should be executed without crash', async () => { + app.get( + '/', + upgradeWebSocket(() => ({ + onClose() { + // doing some stuff here + }, + })) + ) + + const ws = new WebSocket('ws://localhost:3030/') + await new Promise((resolve) => ws.on('open', resolve)) + ws.close() + }) + it('Should be able to send and receive binary content with good length', async () => { const mainPromise = new Promise((resolve) => app.get( @@ -126,7 +142,7 @@ describe('WebSocket helper', () => { await new Promise((resolve) => ws.on('open', resolve)) ws.send(binaryData) - const receivedMessage = await mainPromise; + const receivedMessage = await mainPromise expect(receivedMessage).toBeInstanceOf(Buffer) expect((receivedMessage as Buffer).byteLength).toBe(binaryData.length) diff --git a/packages/node-ws/src/index.ts b/packages/node-ws/src/index.ts index d95f704b..e8a45b8a 100644 --- a/packages/node-ws/src/index.ts +++ b/packages/node-ws/src/index.ts @@ -1,4 +1,3 @@ -import { Buffer } from 'buffer' import type { Server } from 'node:http' import type { Http2SecureServer, Http2Server } from 'node:http2' import type { Hono } from 'hono' @@ -6,6 +5,7 @@ import type { UpgradeWebSocket, WSContext } from 'hono/ws' import type { WebSocket } from 'ws' import { WebSocketServer } from 'ws' import type { IncomingMessage } from 'http' +import { CloseEvent } from './events' export interface NodeWebSocket { upgradeWebSocket: UpgradeWebSocket