mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
@types/bun: Reimplement WebSocket type in default environment (#19017)
This commit is contained in:
8
bun.lock
8
bun.lock
@@ -27,10 +27,8 @@
|
||||
},
|
||||
"packages/bun-types": {
|
||||
"name": "bun-types",
|
||||
"version": "1.2.5",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/ws": "*",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.5.3",
|
||||
@@ -166,8 +164,6 @@
|
||||
|
||||
"@types/semver": ["@types/semver@7.5.8", "", {}, "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="],
|
||||
|
||||
"@types/ws": ["@types/ws@8.5.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w=="],
|
||||
|
||||
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@7.16.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/type-utils": "7.16.1", "@typescript-eslint/utils": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.56.0" } }, "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A=="],
|
||||
|
||||
"@typescript-eslint/parser": ["@typescript-eslint/parser@7.16.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.16.1", "@typescript-eslint/types": "7.16.1", "@typescript-eslint/typescript-estree": "7.16.1", "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA=="],
|
||||
@@ -916,8 +912,6 @@
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
|
||||
"@types/ws/@types/node": ["@types/node@20.12.14", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||
|
||||
"@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
||||
@@ -1008,8 +1002,6 @@
|
||||
|
||||
"@definitelytyped/utils/which/isexe": ["isexe@3.1.1", "", {}, "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ=="],
|
||||
|
||||
"@types/ws/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
|
||||
|
||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||
|
||||
"are-we-there-yet/readable-stream/isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="],
|
||||
|
||||
210
packages/bun-types/bun.d.ts
vendored
210
packages/bun-types/bun.d.ts
vendored
@@ -162,11 +162,6 @@ declare module "bun" {
|
||||
open: Event;
|
||||
}
|
||||
|
||||
interface EventListenerOptions {
|
||||
/** Not directly used by Node.js. Added for API completeness. Default: `false`. */
|
||||
capture?: boolean;
|
||||
}
|
||||
|
||||
interface AddEventListenerOptions extends EventListenerOptions {
|
||||
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
|
||||
once?: boolean;
|
||||
@@ -4264,6 +4259,211 @@ declare module "bun" {
|
||||
compact?: boolean;
|
||||
}
|
||||
|
||||
type WebSocketOptionsProtocolsOrProtocol =
|
||||
| {
|
||||
/**
|
||||
* Protocols to use for the WebSocket connection
|
||||
*/
|
||||
protocols?: string | string[];
|
||||
}
|
||||
| {
|
||||
/**
|
||||
* Protocol to use for the WebSocket connection
|
||||
*/
|
||||
protocol?: string;
|
||||
};
|
||||
|
||||
type WebSocketOptionsTLS = {
|
||||
/**
|
||||
* Options for the TLS connection
|
||||
*/
|
||||
tls?: {
|
||||
/**
|
||||
* Whether to reject the connection if the certificate is not valid
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
rejectUnauthorized?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
type WebSocketOptionsHeaders = {
|
||||
/**
|
||||
* Headers to send to the server
|
||||
*/
|
||||
headers?: import("node:http").OutgoingHttpHeaders;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor options for the `Bun.WebSocket` client
|
||||
*/
|
||||
type WebSocketOptions = WebSocketOptionsProtocolsOrProtocol & WebSocketOptionsTLS & WebSocketOptionsHeaders;
|
||||
|
||||
interface WebSocketEventMap {
|
||||
close: CloseEvent;
|
||||
error: Event;
|
||||
message: MessageEvent;
|
||||
open: Event;
|
||||
}
|
||||
|
||||
/**
|
||||
* A WebSocket client implementation
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ws = new WebSocket("ws://localhost:8080", {
|
||||
* headers: {
|
||||
* "x-custom-header": "hello",
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* ws.addEventListener("open", () => {
|
||||
* console.log("Connected to server");
|
||||
* });
|
||||
*
|
||||
* ws.addEventListener("message", (event) => {
|
||||
* console.log("Received message:", event.data);
|
||||
* });
|
||||
*
|
||||
* ws.send("Hello, server!");
|
||||
* ws.terminate();
|
||||
* ```
|
||||
*/
|
||||
interface WebSocket extends EventTarget {
|
||||
/**
|
||||
* The URL of the WebSocket connection
|
||||
*/
|
||||
readonly url: string;
|
||||
|
||||
/**
|
||||
* Legacy URL property (same as url)
|
||||
* @deprecated Use url instead
|
||||
*/
|
||||
readonly URL: string;
|
||||
|
||||
/**
|
||||
* The current state of the connection
|
||||
*/
|
||||
readonly readyState:
|
||||
| typeof WebSocket.CONNECTING
|
||||
| typeof WebSocket.OPEN
|
||||
| typeof WebSocket.CLOSING
|
||||
| typeof WebSocket.CLOSED;
|
||||
|
||||
/**
|
||||
* The number of bytes of data that have been queued using send() but not yet transmitted to the network
|
||||
*/
|
||||
readonly bufferedAmount: number;
|
||||
|
||||
/**
|
||||
* The protocol selected by the server
|
||||
*/
|
||||
readonly protocol: string;
|
||||
|
||||
/**
|
||||
* The extensions selected by the server
|
||||
*/
|
||||
readonly extensions: string;
|
||||
|
||||
/**
|
||||
* The type of binary data being received.
|
||||
*/
|
||||
binaryType: "arraybuffer" | "nodebuffer";
|
||||
|
||||
/**
|
||||
* Event handler for open event
|
||||
*/
|
||||
onopen: ((this: WebSocket, ev: Event) => any) | null;
|
||||
|
||||
/**
|
||||
* Event handler for message event
|
||||
*/
|
||||
onmessage: ((this: WebSocket, ev: MessageEvent) => any) | null;
|
||||
|
||||
/**
|
||||
* Event handler for error event
|
||||
*/
|
||||
onerror: ((this: WebSocket, ev: Event) => any) | null;
|
||||
|
||||
/**
|
||||
* Event handler for close event
|
||||
*/
|
||||
onclose: ((this: WebSocket, ev: CloseEvent) => any) | null;
|
||||
|
||||
/**
|
||||
* Transmits data to the server
|
||||
* @param data The data to send to the server
|
||||
*/
|
||||
send(data: string | ArrayBufferLike | ArrayBufferView): void;
|
||||
|
||||
/**
|
||||
* Closes the WebSocket connection
|
||||
* @param code A numeric value indicating the status code
|
||||
* @param reason A human-readable string explaining why the connection is closing
|
||||
*/
|
||||
close(code?: number, reason?: string): void;
|
||||
|
||||
/**
|
||||
* Sends a ping frame to the server
|
||||
* @param data Optional data to include in the ping frame
|
||||
*/
|
||||
ping(data?: string | ArrayBufferLike | ArrayBufferView): void;
|
||||
|
||||
/**
|
||||
* Sends a pong frame to the server
|
||||
* @param data Optional data to include in the pong frame
|
||||
*/
|
||||
pong(data?: string | ArrayBufferLike | ArrayBufferView): void;
|
||||
|
||||
/**
|
||||
* Immediately terminates the connection
|
||||
*/
|
||||
terminate(): void;
|
||||
|
||||
/**
|
||||
* Registers an event handler of a specific event type on the WebSocket.
|
||||
* @param type A case-sensitive string representing the event type to listen for
|
||||
* @param listener The function to be called when the event occurs
|
||||
* @param options An options object that specifies characteristics about the event listener
|
||||
*/
|
||||
addEventListener<K extends keyof WebSocketEventMap>(
|
||||
type: K,
|
||||
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
|
||||
options?: boolean | AddEventListenerOptions,
|
||||
): void;
|
||||
addEventListener(
|
||||
type: string,
|
||||
listener: EventListenerOrEventListenerObject,
|
||||
options?: boolean | AddEventListenerOptions,
|
||||
): void;
|
||||
|
||||
/**
|
||||
* Removes an event listener previously registered with addEventListener()
|
||||
* @param type A case-sensitive string representing the event type to remove
|
||||
* @param listener The function to remove from the event target
|
||||
* @param options An options object that specifies characteristics about the event listener
|
||||
*/
|
||||
removeEventListener<K extends keyof WebSocketEventMap>(
|
||||
type: K,
|
||||
listener: (this: WebSocket, ev: WebSocketEventMap[K]) => any,
|
||||
options?: boolean | EventListenerOptions,
|
||||
): void;
|
||||
removeEventListener(
|
||||
type: string,
|
||||
listener: EventListenerOrEventListenerObject,
|
||||
options?: boolean | EventListenerOptions,
|
||||
): void;
|
||||
|
||||
/** @deprecated Use instance property instead */
|
||||
readonly CONNECTING: 0;
|
||||
/** @deprecated Use instance property instead */
|
||||
readonly OPEN: 1;
|
||||
/** @deprecated Use instance property instead */
|
||||
readonly CLOSING: 2;
|
||||
/** @deprecated Use instance property instead */
|
||||
readonly CLOSED: 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretty-print an object the same as {@link console.log} to a `string`
|
||||
*
|
||||
|
||||
70
packages/bun-types/globals.d.ts
vendored
70
packages/bun-types/globals.d.ts
vendored
@@ -11,7 +11,7 @@ declare module "bun" {
|
||||
type NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto;
|
||||
type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey;
|
||||
|
||||
type LibEmptyOrWSWebSocket = LibDomIsLoaded extends true ? {} : import("ws").WebSocket;
|
||||
type LibEmptyOrBunWebSocket = LibDomIsLoaded extends true ? {} : Bun.WebSocket;
|
||||
|
||||
type LibEmptyOrNodeUtilTextEncoder = LibDomIsLoaded extends true ? {} : import("node:util").TextEncoder;
|
||||
|
||||
@@ -63,15 +63,71 @@ declare var Worker: Bun.__internal.UseLibDomIfAvailable<
|
||||
}
|
||||
>;
|
||||
|
||||
interface WebSocket extends Bun.__internal.LibEmptyOrWSWebSocket {}
|
||||
/**
|
||||
* A WebSocket client implementation.
|
||||
*/
|
||||
interface WebSocket extends Bun.__internal.LibEmptyOrBunWebSocket {}
|
||||
/**
|
||||
* A WebSocket client implementation
|
||||
*
|
||||
* If `DOM` is included in tsconfig `lib`, this falls back to the default DOM global `WebSocket`.
|
||||
* Otherwise (when outside of a browser environment), this will be the `WebSocket`
|
||||
* implementation from the `ws` package, which Bun implements.
|
||||
*/
|
||||
declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<"WebSocket", typeof import("ws").WebSocket>;
|
||||
declare var WebSocket: Bun.__internal.UseLibDomIfAvailable<
|
||||
"WebSocket",
|
||||
{
|
||||
prototype: WebSocket;
|
||||
|
||||
/**
|
||||
* Creates a new WebSocket instance with the given URL and options.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
* @param options The options to use for the connection.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ws = new WebSocket("wss://dev.local", {
|
||||
* protocols: ["proto1", "proto2"],
|
||||
* headers: {
|
||||
* "Cookie": "session=123456",
|
||||
* },
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
new (url: string | URL, options?: Bun.WebSocketOptions): WebSocket;
|
||||
|
||||
/**
|
||||
* Creates a new WebSocket instance with the given URL and protocols.
|
||||
*
|
||||
* @param url The URL to connect to.
|
||||
* @param protocols The protocols to use for the connection.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const ws = new WebSocket("wss://dev.local");
|
||||
* const ws = new WebSocket("wss://dev.local", ["proto1", "proto2"]);
|
||||
* ```
|
||||
*/
|
||||
new (url: string | URL, protocols?: string | string[]): WebSocket;
|
||||
|
||||
/**
|
||||
* The connection is not yet open
|
||||
*/
|
||||
readonly CONNECTING: 0;
|
||||
|
||||
/**
|
||||
* The connection is open and ready to communicate
|
||||
*/
|
||||
readonly OPEN: 1;
|
||||
|
||||
/**
|
||||
* The connection is in the process of closing
|
||||
*/
|
||||
readonly CLOSING: 2;
|
||||
|
||||
/**
|
||||
* The connection is closed or couldn't be opened
|
||||
*/
|
||||
readonly CLOSED: 3;
|
||||
}
|
||||
>;
|
||||
|
||||
interface Crypto {
|
||||
readonly subtle: SubtleCrypto;
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
],
|
||||
"homepage": "https://bun.sh",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"@types/ws": "*"
|
||||
"@types/node": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "^1.5.3",
|
||||
|
||||
@@ -122,7 +122,22 @@ describe("@types/bun integration test", () => {
|
||||
"error TS2339: Property 'write' does not exist on type 'ReadableByteStreamController'.",
|
||||
|
||||
"websocket.ts",
|
||||
"error TS2353: Object literal may only specify known properties, and 'headers' does not exist in type 'string[]'.",
|
||||
`error TS2353: Object literal may only specify known properties, and 'protocols' does not exist in type 'string[]'.`,
|
||||
`error TS2353: Object literal may only specify known properties, and 'protocol' does not exist in type 'string[]'.`,
|
||||
`error TS2353: Object literal may only specify known properties, and 'protocol' does not exist in type 'string[]'.`,
|
||||
`error TS2353: Object literal may only specify known properties, and 'headers' does not exist in type 'string[]'.`,
|
||||
`error TS2353: Object literal may only specify known properties, and 'protocols' does not exist in type 'string[]'.`,
|
||||
`error TS2554: Expected 2 arguments, but got 0.`,
|
||||
`error TS2551: Property 'URL' does not exist on type 'WebSocket'. Did you mean 'url'?`,
|
||||
`error TS2339: Property 'ping' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'ping' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'ping' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'ping' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'pong' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'pong' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'pong' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'pong' does not exist on type 'WebSocket'.`,
|
||||
`error TS2339: Property 'terminate' does not exist on type 'WebSocket'.`,
|
||||
|
||||
"worker.ts",
|
||||
"error TS2339: Property 'ref' does not exist on type 'Worker'.",
|
||||
|
||||
@@ -1,15 +1,271 @@
|
||||
export class TestWebSocketClient {
|
||||
#ws: WebSocket;
|
||||
import { expectType } from "./utilities";
|
||||
|
||||
constructor() {
|
||||
this.#ws = new WebSocket("wss://dev.local", {
|
||||
headers: {
|
||||
cookie: "test=test",
|
||||
},
|
||||
});
|
||||
}
|
||||
// WebSocket constructor tests
|
||||
{
|
||||
// Constructor with string URL only
|
||||
new WebSocket("wss://dev.local");
|
||||
|
||||
close() {
|
||||
if (this.#ws != null) this.#ws.close();
|
||||
}
|
||||
// Constructor with string URL and protocols array
|
||||
new WebSocket("wss://dev.local", ["proto1", "proto2"]);
|
||||
|
||||
// Constructor with string URL and single protocol string
|
||||
new WebSocket("wss://dev.local", "proto1");
|
||||
|
||||
// Constructor with URL object only
|
||||
new WebSocket(new URL("wss://dev.local"));
|
||||
|
||||
// Constructor with URL object and protocols array
|
||||
new WebSocket(new URL("wss://dev.local"), ["proto1", "proto2"]);
|
||||
|
||||
// Constructor with URL object and single protocol string
|
||||
new WebSocket(new URL("wss://dev.local"), "proto1");
|
||||
|
||||
// Constructor with string URL and options object with protocols
|
||||
new WebSocket("wss://dev.local", {
|
||||
protocols: ["proto1", "proto2"],
|
||||
});
|
||||
|
||||
// Constructor with string URL and options object with protocol
|
||||
new WebSocket("wss://dev.local", {
|
||||
protocol: "proto1",
|
||||
});
|
||||
|
||||
// Constructor with URL object and options with TLS settings
|
||||
new WebSocket(new URL("wss://dev.local"), {
|
||||
protocol: "proto1",
|
||||
tls: {
|
||||
rejectUnauthorized: false,
|
||||
},
|
||||
});
|
||||
|
||||
// Constructor with headers
|
||||
new WebSocket("wss://dev.local", {
|
||||
headers: {
|
||||
"Cookie": "session=123456",
|
||||
"User-Agent": "BunWebSocketTest",
|
||||
},
|
||||
});
|
||||
|
||||
// Constructor with full options object
|
||||
new WebSocket("wss://dev.local", {
|
||||
protocols: ["proto1", "proto2"],
|
||||
headers: {
|
||||
"Cookie": "session=123456",
|
||||
},
|
||||
tls: {
|
||||
rejectUnauthorized: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Assignability test
|
||||
{
|
||||
function toAny<T>(value: T): any {
|
||||
return value;
|
||||
}
|
||||
|
||||
const AnySocket = toAny(WebSocket);
|
||||
|
||||
const ws: WebSocket = new AnySocket("wss://dev.local");
|
||||
|
||||
ws.close();
|
||||
ws.addEventListener("open", e => expectType(e).is<Event>());
|
||||
ws.addEventListener("message", e => expectType(e).is<MessageEvent>());
|
||||
ws.addEventListener("message", (e: MessageEvent<string>) => expectType(e).is<MessageEvent<string>>());
|
||||
ws.addEventListener("message", (e: MessageEvent<string>) => expectType(e.data).is<string>());
|
||||
}
|
||||
|
||||
// WebSocket static properties test
|
||||
{
|
||||
expectType(WebSocket.CONNECTING).is<0>();
|
||||
expectType(WebSocket.OPEN).is<1>();
|
||||
expectType(WebSocket.CLOSING).is<2>();
|
||||
expectType(WebSocket.CLOSED).is<3>();
|
||||
|
||||
const instance: WebSocket = null as never;
|
||||
expectType(instance.CONNECTING).is<0>();
|
||||
expectType(instance.OPEN).is<1>();
|
||||
expectType(instance.CLOSING).is<2>();
|
||||
expectType(instance.CLOSED).is<3>();
|
||||
}
|
||||
|
||||
// WebSocket event handlers test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Using event handler properties
|
||||
ws.onopen = (event: Event) => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
ws.onmessage = (event: MessageEvent<string>) => {
|
||||
expectType(event.data).is<string>();
|
||||
};
|
||||
|
||||
ws.onerror = (event: Event) => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
ws.onclose = (event: CloseEvent) => {
|
||||
expectType(event).is<CloseEvent>();
|
||||
expectType(event.code).is<number>();
|
||||
expectType(event.reason).is<string>();
|
||||
expectType(event.wasClean).is<boolean>();
|
||||
};
|
||||
|
||||
// Using event handler properties without typing the agument
|
||||
ws.onopen = event => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
ws.onmessage = event => {
|
||||
expectType(event.data).is<any>();
|
||||
|
||||
if (typeof event.data === "string") {
|
||||
expectType(event.data).is<string>();
|
||||
} else if (event.data instanceof ArrayBuffer) {
|
||||
expectType(event.data).is<ArrayBuffer>();
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = event => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
ws.onclose = event => {
|
||||
expectType(event).is<CloseEvent>();
|
||||
expectType(event.code).is<number>();
|
||||
expectType(event.reason).is<string>();
|
||||
expectType(event.wasClean).is<boolean>();
|
||||
};
|
||||
}
|
||||
|
||||
// WebSocket addEventListener test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Event handler functions
|
||||
const handleOpen = (event: Event) => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
const handleMessage = (event: MessageEvent<string>) => {
|
||||
expectType(event.data).is<string>();
|
||||
};
|
||||
|
||||
const handleError = (event: Event) => {
|
||||
expectType(event).is<Event>();
|
||||
};
|
||||
|
||||
const handleClose = (event: CloseEvent) => {
|
||||
expectType(event).is<CloseEvent>();
|
||||
expectType(event.code).is<number>();
|
||||
expectType(event.reason).is<string>();
|
||||
expectType(event.wasClean).is<boolean>();
|
||||
};
|
||||
|
||||
// Add event listeners
|
||||
ws.addEventListener("open", handleOpen);
|
||||
ws.addEventListener("message", handleMessage);
|
||||
ws.addEventListener("error", handleError);
|
||||
ws.addEventListener("close", handleClose);
|
||||
|
||||
// Remove event listeners
|
||||
ws.removeEventListener("open", handleOpen);
|
||||
ws.removeEventListener("message", handleMessage);
|
||||
ws.removeEventListener("error", handleError);
|
||||
ws.removeEventListener("close", handleClose);
|
||||
}
|
||||
|
||||
// WebSocket property access test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Read various properties
|
||||
expectType(ws.readyState).is<0 | 2 | 1 | 3>();
|
||||
expectType(ws.bufferedAmount).is<number>();
|
||||
expectType(ws.url).is<string>();
|
||||
expectType(ws.protocol).is<string>();
|
||||
expectType(ws.extensions).is<string>();
|
||||
|
||||
// Legacy URL property (deprecated but exists)
|
||||
expectType(ws.URL).is<string>();
|
||||
|
||||
// Set binary type
|
||||
ws.binaryType = "arraybuffer";
|
||||
ws.binaryType = "blob";
|
||||
}
|
||||
|
||||
// WebSocket send method test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Send string data
|
||||
ws.send("Hello, server!");
|
||||
|
||||
// Send ArrayBuffer
|
||||
const buffer = new ArrayBuffer(10);
|
||||
ws.send(buffer);
|
||||
|
||||
// Send ArrayBufferView (Uint8Array)
|
||||
const uint8Array = new Uint8Array(buffer);
|
||||
ws.send(uint8Array);
|
||||
|
||||
// --------------------------------------- //
|
||||
// `.send(blob)` is not supported yet
|
||||
// --------------------------------------- //
|
||||
// // Send Blob
|
||||
// const blob = new Blob(["Hello, server!"]);
|
||||
// ws.send(blob);
|
||||
// --------------------------------------- //
|
||||
}
|
||||
|
||||
// WebSocket close method test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Close without parameters
|
||||
ws.close();
|
||||
|
||||
// Close with code
|
||||
ws.close(1000);
|
||||
|
||||
// Close with code and reason
|
||||
ws.close(1001, "Going away");
|
||||
}
|
||||
|
||||
// Bun-specific WebSocket extensions test
|
||||
{
|
||||
const ws = new WebSocket("wss://dev.local");
|
||||
|
||||
// Send ping frame with no data
|
||||
ws.ping();
|
||||
|
||||
// Send ping frame with string data
|
||||
ws.ping("ping data");
|
||||
|
||||
// Send ping frame with ArrayBuffer
|
||||
const pingBuffer = new ArrayBuffer(4);
|
||||
ws.ping(pingBuffer);
|
||||
|
||||
// Send ping frame with ArrayBufferView
|
||||
const pingView = new Uint8Array(pingBuffer);
|
||||
ws.ping(pingView);
|
||||
|
||||
// Send pong frame with no data
|
||||
ws.pong();
|
||||
|
||||
// Send pong frame with string data
|
||||
ws.pong("pong data");
|
||||
|
||||
// Send pong frame with ArrayBuffer
|
||||
const pongBuffer = new ArrayBuffer(4);
|
||||
ws.pong(pongBuffer);
|
||||
|
||||
// Send pong frame with ArrayBufferView
|
||||
const pongView = new Uint8Array(pongBuffer);
|
||||
ws.pong(pongView);
|
||||
|
||||
// Terminate the connection immediately
|
||||
ws.terminate();
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
import { WebSocket, WebSocketServer } from "ws";
|
||||
|
||||
const ws = new WebSocket("ws://www.host.com/path");
|
||||
|
||||
ws.send("asdf");
|
||||
|
||||
const wss = new WebSocketServer({
|
||||
port: 8080,
|
||||
perMessageDeflate: false,
|
||||
});
|
||||
wss;
|
||||
Reference in New Issue
Block a user