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": {
|
"packages/bun-types": {
|
||||||
"name": "bun-types",
|
"name": "bun-types",
|
||||||
"version": "1.2.5",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/ws": "*",
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.5.3",
|
"@biomejs/biome": "^1.5.3",
|
||||||
@@ -166,8 +164,6 @@
|
|||||||
|
|
||||||
"@types/semver": ["@types/semver@7.5.8", "", {}, "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ=="],
|
"@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/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=="],
|
"@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=="],
|
"@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/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=="],
|
"@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=="],
|
"@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=="],
|
"@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=="],
|
"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;
|
open: Event;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface EventListenerOptions {
|
|
||||||
/** Not directly used by Node.js. Added for API completeness. Default: `false`. */
|
|
||||||
capture?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AddEventListenerOptions extends EventListenerOptions {
|
interface AddEventListenerOptions extends EventListenerOptions {
|
||||||
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
|
/** When `true`, the listener is automatically removed when it is first invoked. Default: `false`. */
|
||||||
once?: boolean;
|
once?: boolean;
|
||||||
@@ -4264,6 +4259,211 @@ declare module "bun" {
|
|||||||
compact?: boolean;
|
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`
|
* 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 NodeCryptoWebcryptoSubtleCrypto = import("crypto").webcrypto.SubtleCrypto;
|
||||||
type NodeCryptoWebcryptoCryptoKey = import("crypto").webcrypto.CryptoKey;
|
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;
|
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
|
* 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 {
|
interface Crypto {
|
||||||
readonly subtle: SubtleCrypto;
|
readonly subtle: SubtleCrypto;
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
],
|
],
|
||||||
"homepage": "https://bun.sh",
|
"homepage": "https://bun.sh",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*"
|
||||||
"@types/ws": "*"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "^1.5.3",
|
"@biomejs/biome": "^1.5.3",
|
||||||
|
|||||||
@@ -122,7 +122,22 @@ describe("@types/bun integration test", () => {
|
|||||||
"error TS2339: Property 'write' does not exist on type 'ReadableByteStreamController'.",
|
"error TS2339: Property 'write' does not exist on type 'ReadableByteStreamController'.",
|
||||||
|
|
||||||
"websocket.ts",
|
"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",
|
"worker.ts",
|
||||||
"error TS2339: Property 'ref' does not exist on type 'Worker'.",
|
"error TS2339: Property 'ref' does not exist on type 'Worker'.",
|
||||||
|
|||||||
@@ -1,15 +1,271 @@
|
|||||||
export class TestWebSocketClient {
|
import { expectType } from "./utilities";
|
||||||
#ws: WebSocket;
|
|
||||||
|
|
||||||
constructor() {
|
// WebSocket constructor tests
|
||||||
this.#ws = new WebSocket("wss://dev.local", {
|
{
|
||||||
headers: {
|
// Constructor with string URL only
|
||||||
cookie: "test=test",
|
new WebSocket("wss://dev.local");
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
// Constructor with string URL and protocols array
|
||||||
if (this.#ws != null) this.#ws.close();
|
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