crossws 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +46 -0
- package/README.md +187 -0
- package/dist/adapters/bun.cjs +57 -0
- package/dist/adapters/bun.d.cts +43 -0
- package/dist/adapters/bun.d.mts +43 -0
- package/dist/adapters/bun.d.ts +43 -0
- package/dist/adapters/bun.mjs +52 -0
- package/dist/adapters/deno.cjs +57 -0
- package/dist/adapters/deno.d.cts +18 -0
- package/dist/adapters/deno.d.mts +18 -0
- package/dist/adapters/deno.d.ts +18 -0
- package/dist/adapters/deno.mjs +52 -0
- package/dist/adapters/node.cjs +4529 -0
- package/dist/adapters/node.d.cts +299 -0
- package/dist/adapters/node.d.mts +299 -0
- package/dist/adapters/node.d.ts +299 -0
- package/dist/adapters/node.mjs +4511 -0
- package/dist/index.cjs +13 -0
- package/dist/index.d.cts +37 -0
- package/dist/index.d.mts +37 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.mjs +7 -0
- package/dist/shared/crossws.002417e5.cjs +56 -0
- package/dist/shared/crossws.08866fa6.mjs +51 -0
- package/package.json +67 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Pooya Parsa <pooya@pi0.io>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
Bundled with https://github.com/websockets/ws
|
|
26
|
+
|
|
27
|
+
Copyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>
|
|
28
|
+
Copyright (c) 2013 Arnout Kazemier and contributors
|
|
29
|
+
Copyright (c) 2016 Luigi Pinca and contributors
|
|
30
|
+
|
|
31
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
32
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
33
|
+
the Software without restriction, including without limitation the rights to
|
|
34
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
35
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
36
|
+
subject to the following conditions:
|
|
37
|
+
|
|
38
|
+
The above copyright notice and this permission notice shall be included in all
|
|
39
|
+
copies or substantial portions of the Software.
|
|
40
|
+
|
|
41
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
42
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
43
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
44
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
45
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
46
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# ⛨ CrossWS
|
|
2
|
+
|
|
3
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
4
|
+
[![bundle][bundle-src]][bundle-href]
|
|
5
|
+
|
|
6
|
+
<!-- [![npm downloads][npm-downloads-src]][npm-downloads-href] -->
|
|
7
|
+
|
|
8
|
+
<!-- [![Codecov][codecov-src]][codecov-href] -->
|
|
9
|
+
|
|
10
|
+
> [!WARNING]
|
|
11
|
+
> This project and API are under heavy development and trial. Please don't rely on it for production yet. Feedback is more than welcome!
|
|
12
|
+
|
|
13
|
+
Cross-platform WebSocket Servers:
|
|
14
|
+
|
|
15
|
+
- Elegant, typed, and simple interface to define your WebSocket server handlers
|
|
16
|
+
- Performant per-server handlers instead of per-connection events API ([why](https://bun.sh/docs/api/websockets#lcYFjkFYJC-summary))
|
|
17
|
+
- Zero dependencies with bundled [ws](https://github.com/websockets/ws) types and runtime for [Node.js](https://nodejs.org/) support
|
|
18
|
+
- Native integration with [Bun](https://bun.sh/) and [Deno](https://deno.com/) WebSocket API
|
|
19
|
+
- Super lightweight tree-shakable packaging
|
|
20
|
+
- Developer-Friendly logging
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
# npm
|
|
26
|
+
npm install crossws
|
|
27
|
+
|
|
28
|
+
# yarn
|
|
29
|
+
yarn add crossws
|
|
30
|
+
|
|
31
|
+
# pnpm
|
|
32
|
+
pnpm install crossws
|
|
33
|
+
|
|
34
|
+
# bun
|
|
35
|
+
bun install crossws
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Integration
|
|
39
|
+
|
|
40
|
+
CrossWS allows integrating your WebSocket handlers with different runtimes and platforms using built-in adapters. Each runtime has a specific method of integrating WebSocket. Once integrated, your custom handlers (such as `onMessage`) will work consistently even if you change the runtime!
|
|
41
|
+
|
|
42
|
+
### Integration with **Node.js**
|
|
43
|
+
|
|
44
|
+
To integrate CrossWS with your Node.js HTTP server, you need to connect the `upgrade` event to the `handleUpgrade` method returned from the adapter. Behind the scenes, CrossWS uses an embedded version of [ws](https://github.com/websockets/ws).
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
// Initialize Server
|
|
48
|
+
import { createServer } from "node:http";
|
|
49
|
+
|
|
50
|
+
const server = createServer((req, res) => {
|
|
51
|
+
res.end(
|
|
52
|
+
`<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
|
|
53
|
+
);
|
|
54
|
+
}).listen(3000);
|
|
55
|
+
|
|
56
|
+
// Initialize WebSocket Handler
|
|
57
|
+
import nodeWSAdapter from "crossws/adapters/node";
|
|
58
|
+
|
|
59
|
+
const { handleUpgrade } = nodeWSAdapter({ onMessage: console.log });
|
|
60
|
+
server.on("upgrade", handleUpgrade);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
See [playground/node.ts](./playground/node.ts) for demo and [src/adapters/node.ts](./src/adapters/node.ts) for implementation.
|
|
64
|
+
|
|
65
|
+
## Integration with **Bun**
|
|
66
|
+
|
|
67
|
+
To integrate crosws with your Bun server, you need to check for `server.upgrade` and also pass the `websocket` object returned from the adapter to server options. CrossWS leverages native Bun WebSocket API.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import bunAdapter from "./dist/adapters/bun";
|
|
71
|
+
|
|
72
|
+
const { websocket } = bunAdapter({ onMessage: console.log });
|
|
73
|
+
|
|
74
|
+
Bun.serve({
|
|
75
|
+
port: 3000,
|
|
76
|
+
fetch(req, server) {
|
|
77
|
+
if (server.upgrade(req)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
return new Response(
|
|
81
|
+
`<script>new WebSocket("ws://localhost:3000").addEventListener('open', (e) => e.target.send("Hello from client!"));</script>`,
|
|
82
|
+
{ headers: { "content-type": "text/html" } },
|
|
83
|
+
);
|
|
84
|
+
},
|
|
85
|
+
websocket,
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
See [playground/bun.ts](./playground/bun.ts) for demo and [src/adapters/bun.ts](./src/adapters/bun.ts) for implementation.
|
|
90
|
+
|
|
91
|
+
## Integration with **Deno**
|
|
92
|
+
|
|
93
|
+
To integrate CrossWS with your Deno server, you need to check for the `upgrade` header and then call `handleUpgrade` method from the adapter passing the incoming request object. The returned value is the server upgrade response.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import denoAdapter from "crossws/adapters/deno";
|
|
97
|
+
|
|
98
|
+
const { handleUpgrade } = denoAdapter({ onMessage: console.log });
|
|
99
|
+
|
|
100
|
+
Deno.serve({ port: 3000 }, (req) => {
|
|
101
|
+
if (req.headers.get("upgrade") === "websocket") {
|
|
102
|
+
return handleUpgrade(req);
|
|
103
|
+
}
|
|
104
|
+
return new Response(
|
|
105
|
+
`<script>new WebSocket("ws://localhost:3000").addEventListener("open", (e) => e.target.send("Hello from client!"));</script>`,
|
|
106
|
+
{ headers: { "content-type": "text/html" } },
|
|
107
|
+
);
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
See [playground/deno.ts](./playground/deno.ts) for demo and [src/adapters/deno.ts](./src/adapters/deno.ts) for implementation.
|
|
112
|
+
|
|
113
|
+
## Integration with other runtimes
|
|
114
|
+
|
|
115
|
+
You can define your custom adapters using `defineWebSocketAdapter` wrapper.
|
|
116
|
+
|
|
117
|
+
See other adapter implementations in [./src/adapters](./src/adapters/) to get and idea how adapters can be implemented and feel free to directly make a Pull Request to support your environment in CrossWS!
|
|
118
|
+
|
|
119
|
+
## Handler API
|
|
120
|
+
|
|
121
|
+
Previously you saw in the adapter examples that we pass `onMessage` option.
|
|
122
|
+
|
|
123
|
+
First object passed to adapters is a list of global handlers that will get called during lifecycle of a WebSocket connection. You can use `defineWebSocketHandler` utility to make a typed websocket handler object and pass it to the actual adapter when needed.
|
|
124
|
+
|
|
125
|
+
**Note: API is subject to change! Feedbacks Welcome!**
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
import { defineWebSocketHandler } from "crossws";
|
|
129
|
+
|
|
130
|
+
const websocketHandler = defineWebSocketHandler({
|
|
131
|
+
onMessage: (peer, message) => {
|
|
132
|
+
console.log("message", peer, message);
|
|
133
|
+
if (message.text().includes("ping")) {
|
|
134
|
+
peer.send("pong");
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
onError: (peer, error) => {
|
|
138
|
+
console.log("error", peer, error);
|
|
139
|
+
},
|
|
140
|
+
onOpen: (peer) => {
|
|
141
|
+
console.log("open", peer);
|
|
142
|
+
},
|
|
143
|
+
onClose: (peer, code, reason) => {
|
|
144
|
+
console.log("close", peer, code, reason);
|
|
145
|
+
},
|
|
146
|
+
onEvent: (event, ...args) => {
|
|
147
|
+
console.log("event", event);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `WebSocketPeer`
|
|
153
|
+
|
|
154
|
+
Websocket handler methods accept a peer instance as first argument. peer is a wrapper over platform natives WebSocket connection instance and alows to send message.
|
|
155
|
+
|
|
156
|
+
**Tip:** You can safely log a peer instance to console using `console.log` it will be automatically stringified with useful information including remote address and connection status!
|
|
157
|
+
|
|
158
|
+
### `WebSocketMessage`
|
|
159
|
+
|
|
160
|
+
Second argument to `onMessage` event handler is a message object. You can access raw data using `message.rawData` or stringified message using `message.text()`.
|
|
161
|
+
|
|
162
|
+
**Tip:** You can safely log `message` object to console using `console.log` it will be automatically stringified!
|
|
163
|
+
|
|
164
|
+
## Development
|
|
165
|
+
|
|
166
|
+
- Clone this repository
|
|
167
|
+
- Install latest LTS version of [Node.js](https://nodejs.org/en/)
|
|
168
|
+
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
|
|
169
|
+
- Install dependencies using `pnpm install`
|
|
170
|
+
- Run interactive tests using `pnpm dev`
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
Made with 💛
|
|
175
|
+
|
|
176
|
+
Published under [MIT License](./LICENSE).
|
|
177
|
+
|
|
178
|
+
<!-- Badges -->
|
|
179
|
+
|
|
180
|
+
[npm-version-src]: https://img.shields.io/npm/v/crossws?style=flat&colorA=18181B&colorB=F0DB4F
|
|
181
|
+
[npm-version-href]: https://npmjs.com/package/crossws
|
|
182
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/crossws?style=flat&colorA=18181B&colorB=F0DB4F
|
|
183
|
+
[npm-downloads-href]: https://npmjs.com/package/crossws
|
|
184
|
+
[codecov-src]: https://img.shields.io/codecov/c/gh/unjs/crossws/main?style=flat&colorA=18181B&colorB=F0DB4F
|
|
185
|
+
[codecov-href]: https://codecov.io/gh/unjs/crossws
|
|
186
|
+
[bundle-src]: https://img.shields.io/bundlephobia/minzip/crossws?style=flat&colorA=18181B&colorB=F0DB4F
|
|
187
|
+
[bundle-href]: https://bundlephobia.com/result?p=crossws
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const peer = require('../shared/crossws.002417e5.cjs');
|
|
6
|
+
|
|
7
|
+
const WebSocket = globalThis.WebSocket;
|
|
8
|
+
const bun = peer.defineWebSocketAdapter(
|
|
9
|
+
(handler, opts = {}) => {
|
|
10
|
+
return {
|
|
11
|
+
websocket: {
|
|
12
|
+
message: (ws, message) => {
|
|
13
|
+
handler.onEvent?.("bun:message", ws, message);
|
|
14
|
+
const peer$1 = new BunWebSocketPeer(ws);
|
|
15
|
+
handler.onMessage?.(peer$1, new peer.WebSocketMessage(message));
|
|
16
|
+
},
|
|
17
|
+
open: (ws) => {
|
|
18
|
+
handler.onEvent?.("bun:open", ws);
|
|
19
|
+
const peer = new BunWebSocketPeer(ws);
|
|
20
|
+
handler.onOpen?.(peer);
|
|
21
|
+
},
|
|
22
|
+
close: (ws) => {
|
|
23
|
+
handler.onEvent?.("bun:close", ws);
|
|
24
|
+
const peer = new BunWebSocketPeer(ws);
|
|
25
|
+
handler.onClose?.(peer, 0, "");
|
|
26
|
+
},
|
|
27
|
+
error: (ws, error) => {
|
|
28
|
+
handler.onEvent?.("bun:error", ws, error);
|
|
29
|
+
const peer$1 = new BunWebSocketPeer(ws);
|
|
30
|
+
handler.onError?.(peer$1, new peer.WebSocketError(error));
|
|
31
|
+
},
|
|
32
|
+
drain: (ws) => {
|
|
33
|
+
handler.onEvent?.("bun:drain", ws);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
class BunWebSocketPeer extends peer.WebSocketPeer {
|
|
40
|
+
constructor(_ws) {
|
|
41
|
+
super();
|
|
42
|
+
this._ws = _ws;
|
|
43
|
+
}
|
|
44
|
+
get id() {
|
|
45
|
+
return this._ws.remoteAddress;
|
|
46
|
+
}
|
|
47
|
+
get readyState() {
|
|
48
|
+
return this._ws.readyState;
|
|
49
|
+
}
|
|
50
|
+
send(message) {
|
|
51
|
+
this._ws.send(message);
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exports.WebSocket = WebSocket;
|
|
57
|
+
exports.default = bun;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.cjs';
|
|
2
|
+
|
|
3
|
+
interface BunWSOptions {
|
|
4
|
+
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
+
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
+
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
+
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
+
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
+
perMessageDeflate?: boolean | {
|
|
10
|
+
compress?: boolean | BunWSCompressor;
|
|
11
|
+
decompress?: boolean | BunWSCompressor;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
+
interface BunServerWebSocket {
|
|
16
|
+
readonly data: any;
|
|
17
|
+
readonly readyState: number;
|
|
18
|
+
readonly remoteAddress: string;
|
|
19
|
+
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
+
close(code?: number, reason?: string): void;
|
|
21
|
+
subscribe(topic: string): void;
|
|
22
|
+
unsubscribe(topic: string): void;
|
|
23
|
+
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
+
isSubscribed(topic: string): boolean;
|
|
25
|
+
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const WebSocket: {
|
|
29
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
+
prototype: WebSocket;
|
|
31
|
+
readonly CONNECTING: 0;
|
|
32
|
+
readonly OPEN: 1;
|
|
33
|
+
readonly CLOSING: 2;
|
|
34
|
+
readonly CLOSED: 3;
|
|
35
|
+
};
|
|
36
|
+
interface AdapterOptions {
|
|
37
|
+
}
|
|
38
|
+
interface Adapter {
|
|
39
|
+
websocket: BunWSOptions;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
|
+
|
|
43
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.mjs';
|
|
2
|
+
|
|
3
|
+
interface BunWSOptions {
|
|
4
|
+
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
+
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
+
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
+
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
+
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
+
perMessageDeflate?: boolean | {
|
|
10
|
+
compress?: boolean | BunWSCompressor;
|
|
11
|
+
decompress?: boolean | BunWSCompressor;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
+
interface BunServerWebSocket {
|
|
16
|
+
readonly data: any;
|
|
17
|
+
readonly readyState: number;
|
|
18
|
+
readonly remoteAddress: string;
|
|
19
|
+
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
+
close(code?: number, reason?: string): void;
|
|
21
|
+
subscribe(topic: string): void;
|
|
22
|
+
unsubscribe(topic: string): void;
|
|
23
|
+
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
+
isSubscribed(topic: string): boolean;
|
|
25
|
+
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const WebSocket: {
|
|
29
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
+
prototype: WebSocket;
|
|
31
|
+
readonly CONNECTING: 0;
|
|
32
|
+
readonly OPEN: 1;
|
|
33
|
+
readonly CLOSING: 2;
|
|
34
|
+
readonly CLOSED: 3;
|
|
35
|
+
};
|
|
36
|
+
interface AdapterOptions {
|
|
37
|
+
}
|
|
38
|
+
interface Adapter {
|
|
39
|
+
websocket: BunWSOptions;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
|
+
|
|
43
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.js';
|
|
2
|
+
|
|
3
|
+
interface BunWSOptions {
|
|
4
|
+
message: (ws: BunServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
5
|
+
open?: (ws: BunServerWebSocket) => void;
|
|
6
|
+
close?: (ws: BunServerWebSocket) => void;
|
|
7
|
+
error?: (ws: BunServerWebSocket, error: Error) => void;
|
|
8
|
+
drain?: (ws: BunServerWebSocket) => void;
|
|
9
|
+
perMessageDeflate?: boolean | {
|
|
10
|
+
compress?: boolean | BunWSCompressor;
|
|
11
|
+
decompress?: boolean | BunWSCompressor;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
type BunWSCompressor = `"disable"` | `"shared"` | `"dedicated"` | `"3KB"` | `"4KB"` | `"8KB"` | `"16KB"` | `"32KB"` | `"64KB"` | `"128KB"` | `"256KB"`;
|
|
15
|
+
interface BunServerWebSocket {
|
|
16
|
+
readonly data: any;
|
|
17
|
+
readonly readyState: number;
|
|
18
|
+
readonly remoteAddress: string;
|
|
19
|
+
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
20
|
+
close(code?: number, reason?: string): void;
|
|
21
|
+
subscribe(topic: string): void;
|
|
22
|
+
unsubscribe(topic: string): void;
|
|
23
|
+
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
24
|
+
isSubscribed(topic: string): boolean;
|
|
25
|
+
cork(cb: (ws: BunServerWebSocket) => void): void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
declare const WebSocket: {
|
|
29
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
30
|
+
prototype: WebSocket;
|
|
31
|
+
readonly CONNECTING: 0;
|
|
32
|
+
readonly OPEN: 1;
|
|
33
|
+
readonly CLOSING: 2;
|
|
34
|
+
readonly CLOSED: 3;
|
|
35
|
+
};
|
|
36
|
+
interface AdapterOptions {
|
|
37
|
+
}
|
|
38
|
+
interface Adapter {
|
|
39
|
+
websocket: BunWSOptions;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
42
|
+
|
|
43
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeer } from '../shared/crossws.08866fa6.mjs';
|
|
2
|
+
|
|
3
|
+
const WebSocket = globalThis.WebSocket;
|
|
4
|
+
const bun = defineWebSocketAdapter(
|
|
5
|
+
(handler, opts = {}) => {
|
|
6
|
+
return {
|
|
7
|
+
websocket: {
|
|
8
|
+
message: (ws, message) => {
|
|
9
|
+
handler.onEvent?.("bun:message", ws, message);
|
|
10
|
+
const peer = new BunWebSocketPeer(ws);
|
|
11
|
+
handler.onMessage?.(peer, new WebSocketMessage(message));
|
|
12
|
+
},
|
|
13
|
+
open: (ws) => {
|
|
14
|
+
handler.onEvent?.("bun:open", ws);
|
|
15
|
+
const peer = new BunWebSocketPeer(ws);
|
|
16
|
+
handler.onOpen?.(peer);
|
|
17
|
+
},
|
|
18
|
+
close: (ws) => {
|
|
19
|
+
handler.onEvent?.("bun:close", ws);
|
|
20
|
+
const peer = new BunWebSocketPeer(ws);
|
|
21
|
+
handler.onClose?.(peer, 0, "");
|
|
22
|
+
},
|
|
23
|
+
error: (ws, error) => {
|
|
24
|
+
handler.onEvent?.("bun:error", ws, error);
|
|
25
|
+
const peer = new BunWebSocketPeer(ws);
|
|
26
|
+
handler.onError?.(peer, new WebSocketError(error));
|
|
27
|
+
},
|
|
28
|
+
drain: (ws) => {
|
|
29
|
+
handler.onEvent?.("bun:drain", ws);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
class BunWebSocketPeer extends WebSocketPeer {
|
|
36
|
+
constructor(_ws) {
|
|
37
|
+
super();
|
|
38
|
+
this._ws = _ws;
|
|
39
|
+
}
|
|
40
|
+
get id() {
|
|
41
|
+
return this._ws.remoteAddress;
|
|
42
|
+
}
|
|
43
|
+
get readyState() {
|
|
44
|
+
return this._ws.readyState;
|
|
45
|
+
}
|
|
46
|
+
send(message) {
|
|
47
|
+
this._ws.send(message);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { WebSocket, bun as default };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
const peer = require('../shared/crossws.002417e5.cjs');
|
|
6
|
+
|
|
7
|
+
const WebSocket = globalThis.WebSocket;
|
|
8
|
+
const deno = peer.defineWebSocketAdapter(
|
|
9
|
+
(handler, opts = {}) => {
|
|
10
|
+
const handleUpgrade = (req) => {
|
|
11
|
+
const upgrade = Deno.upgradeWebSocket(req);
|
|
12
|
+
upgrade.socket.addEventListener("open", () => {
|
|
13
|
+
handler.onEvent?.("deno:open", upgrade.socket);
|
|
14
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
15
|
+
handler.onOpen?.(peer);
|
|
16
|
+
});
|
|
17
|
+
upgrade.socket.addEventListener("message", (event) => {
|
|
18
|
+
handler.onEvent?.("deno:message", upgrade.socket, event);
|
|
19
|
+
const peer$1 = new DenoWebSocketPeer(upgrade.socket);
|
|
20
|
+
handler.onMessage?.(peer$1, new peer.WebSocketMessage(event.data));
|
|
21
|
+
});
|
|
22
|
+
upgrade.socket.addEventListener("close", () => {
|
|
23
|
+
handler.onEvent?.("deno:close", upgrade.socket);
|
|
24
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
25
|
+
handler.onClose?.(peer, 0, "");
|
|
26
|
+
});
|
|
27
|
+
upgrade.socket.addEventListener("error", (error) => {
|
|
28
|
+
handler.onEvent?.("deno:error", upgrade.socket, error);
|
|
29
|
+
const peer$1 = new DenoWebSocketPeer(upgrade.socket);
|
|
30
|
+
handler.onError?.(peer$1, new peer.WebSocketError(error));
|
|
31
|
+
});
|
|
32
|
+
return upgrade.response;
|
|
33
|
+
};
|
|
34
|
+
return {
|
|
35
|
+
handleUpgrade
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
class DenoWebSocketPeer extends peer.WebSocketPeer {
|
|
40
|
+
constructor(_ws) {
|
|
41
|
+
super();
|
|
42
|
+
this._ws = _ws;
|
|
43
|
+
}
|
|
44
|
+
get id() {
|
|
45
|
+
return this._ws.remoteAddress;
|
|
46
|
+
}
|
|
47
|
+
get readyState() {
|
|
48
|
+
return this._ws.readyState;
|
|
49
|
+
}
|
|
50
|
+
send(message) {
|
|
51
|
+
this._ws.send(message);
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
exports.WebSocket = WebSocket;
|
|
57
|
+
exports.default = deno;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.cjs';
|
|
2
|
+
|
|
3
|
+
declare const WebSocket: {
|
|
4
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
5
|
+
readonly prototype: WebSocket;
|
|
6
|
+
readonly CLOSED: number;
|
|
7
|
+
readonly CLOSING: number;
|
|
8
|
+
readonly CONNECTING: number;
|
|
9
|
+
readonly OPEN: number;
|
|
10
|
+
};
|
|
11
|
+
interface AdapterOptions {
|
|
12
|
+
}
|
|
13
|
+
interface Adapter {
|
|
14
|
+
handleUpgrade(req: Deno.Request): Response;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
17
|
+
|
|
18
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.mjs';
|
|
2
|
+
|
|
3
|
+
declare const WebSocket: {
|
|
4
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
5
|
+
readonly prototype: WebSocket;
|
|
6
|
+
readonly CLOSED: number;
|
|
7
|
+
readonly CLOSING: number;
|
|
8
|
+
readonly CONNECTING: number;
|
|
9
|
+
readonly OPEN: number;
|
|
10
|
+
};
|
|
11
|
+
interface AdapterOptions {
|
|
12
|
+
}
|
|
13
|
+
interface Adapter {
|
|
14
|
+
handleUpgrade(req: Deno.Request): Response;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
17
|
+
|
|
18
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebSocketAdapter } from '../index.js';
|
|
2
|
+
|
|
3
|
+
declare const WebSocket: {
|
|
4
|
+
new (url: string | URL, protocols?: string | string[] | undefined): WebSocket;
|
|
5
|
+
readonly prototype: WebSocket;
|
|
6
|
+
readonly CLOSED: number;
|
|
7
|
+
readonly CLOSING: number;
|
|
8
|
+
readonly CONNECTING: number;
|
|
9
|
+
readonly OPEN: number;
|
|
10
|
+
};
|
|
11
|
+
interface AdapterOptions {
|
|
12
|
+
}
|
|
13
|
+
interface Adapter {
|
|
14
|
+
handleUpgrade(req: Deno.Request): Response;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: WebSocketAdapter<Adapter, AdapterOptions>;
|
|
17
|
+
|
|
18
|
+
export { type Adapter, type AdapterOptions, WebSocket, _default as default };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { d as defineWebSocketAdapter, a as WebSocketMessage, W as WebSocketError, b as WebSocketPeer } from '../shared/crossws.08866fa6.mjs';
|
|
2
|
+
|
|
3
|
+
const WebSocket = globalThis.WebSocket;
|
|
4
|
+
const deno = defineWebSocketAdapter(
|
|
5
|
+
(handler, opts = {}) => {
|
|
6
|
+
const handleUpgrade = (req) => {
|
|
7
|
+
const upgrade = Deno.upgradeWebSocket(req);
|
|
8
|
+
upgrade.socket.addEventListener("open", () => {
|
|
9
|
+
handler.onEvent?.("deno:open", upgrade.socket);
|
|
10
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
11
|
+
handler.onOpen?.(peer);
|
|
12
|
+
});
|
|
13
|
+
upgrade.socket.addEventListener("message", (event) => {
|
|
14
|
+
handler.onEvent?.("deno:message", upgrade.socket, event);
|
|
15
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
16
|
+
handler.onMessage?.(peer, new WebSocketMessage(event.data));
|
|
17
|
+
});
|
|
18
|
+
upgrade.socket.addEventListener("close", () => {
|
|
19
|
+
handler.onEvent?.("deno:close", upgrade.socket);
|
|
20
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
21
|
+
handler.onClose?.(peer, 0, "");
|
|
22
|
+
});
|
|
23
|
+
upgrade.socket.addEventListener("error", (error) => {
|
|
24
|
+
handler.onEvent?.("deno:error", upgrade.socket, error);
|
|
25
|
+
const peer = new DenoWebSocketPeer(upgrade.socket);
|
|
26
|
+
handler.onError?.(peer, new WebSocketError(error));
|
|
27
|
+
});
|
|
28
|
+
return upgrade.response;
|
|
29
|
+
};
|
|
30
|
+
return {
|
|
31
|
+
handleUpgrade
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
class DenoWebSocketPeer extends WebSocketPeer {
|
|
36
|
+
constructor(_ws) {
|
|
37
|
+
super();
|
|
38
|
+
this._ws = _ws;
|
|
39
|
+
}
|
|
40
|
+
get id() {
|
|
41
|
+
return this._ws.remoteAddress;
|
|
42
|
+
}
|
|
43
|
+
get readyState() {
|
|
44
|
+
return this._ws.readyState;
|
|
45
|
+
}
|
|
46
|
+
send(message) {
|
|
47
|
+
this._ws.send(message);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { WebSocket, deno as default };
|