@zimic/ws 0.1.0-canary.0
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.md +16 -0
- package/README.md +51 -0
- package/dist/index.d.ts +149 -0
- package/dist/index.js +259 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +249 -0
- package/dist/index.mjs.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.js +112 -0
- package/dist/server.js.map +1 -0
- package/dist/server.mjs +110 -0
- package/dist/server.mjs.map +1 -0
- package/index.d.ts +1 -0
- package/package.json +114 -0
- package/server.d.ts +1 -0
- package/src/client/ClientSocket.ts +7 -0
- package/src/client/WebSocketClient.ts +228 -0
- package/src/client/utils/lifecycle.ts +89 -0
- package/src/errors/WebSocketCloseTimeoutError.ts +8 -0
- package/src/errors/WebSocketMessageAbortError.ts +8 -0
- package/src/errors/WebSocketOpenTimeoutError.ts +8 -0
- package/src/errors/WebSocketTimeoutError.ts +6 -0
- package/src/index.ts +6 -0
- package/src/server/ServerSocket.ts +1 -0
- package/src/server/WebSocketServer.ts +45 -0
- package/src/server/index.ts +2 -0
- package/src/server/utils/lifecycle.ts +81 -0
- package/src/types/json.ts +8 -0
- package/src/types/schema.ts +35 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import NodeWebSocket from 'ws';
|
|
2
|
+
|
|
3
|
+
// src/errors/WebSocketTimeoutError.ts
|
|
4
|
+
var WebSocketTimeoutError = class extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = "WebSocketTimeoutError";
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// src/errors/WebSocketCloseTimeoutError.ts
|
|
12
|
+
var WebSocketCloseTimeoutError = class extends WebSocketTimeoutError {
|
|
13
|
+
constructor(reachedTimeout) {
|
|
14
|
+
super(`Web socket close timed out after ${reachedTimeout}ms.`);
|
|
15
|
+
this.name = "WebSocketCloseTimeoutError";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// src/errors/WebSocketMessageAbortError.ts
|
|
20
|
+
var WebSocketMessageAbortError = class extends WebSocketTimeoutError {
|
|
21
|
+
constructor() {
|
|
22
|
+
super("Web socket message was aborted.");
|
|
23
|
+
this.name = "WebSocketMessageAbortError";
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// src/errors/WebSocketOpenTimeoutError.ts
|
|
28
|
+
var WebSocketOpenTimeoutError = class extends WebSocketTimeoutError {
|
|
29
|
+
constructor(reachedTimeout) {
|
|
30
|
+
super(`Web socket open timed out after ${reachedTimeout}ms.`);
|
|
31
|
+
this.name = "WebSocketOpenTimeoutError";
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
var isNativeWebSocketAvailable = typeof WebSocket !== "undefined";
|
|
35
|
+
var ClientSocket = isNativeWebSocketAvailable ? WebSocket : NodeWebSocket;
|
|
36
|
+
|
|
37
|
+
// src/client/utils/lifecycle.ts
|
|
38
|
+
async function openClientSocket(socket, options = {}) {
|
|
39
|
+
const { timeout: timeoutDuration } = options;
|
|
40
|
+
const isAlreadyOpen = socket.readyState === socket.OPEN;
|
|
41
|
+
if (isAlreadyOpen) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
await new Promise((resolve, reject) => {
|
|
45
|
+
function removeAllSocketListeners() {
|
|
46
|
+
socket.removeEventListener("open", handleOpenSuccess);
|
|
47
|
+
socket.removeEventListener("error", handleError);
|
|
48
|
+
socket.removeEventListener("close", handleError);
|
|
49
|
+
}
|
|
50
|
+
function handleError(error) {
|
|
51
|
+
removeAllSocketListeners();
|
|
52
|
+
reject(error);
|
|
53
|
+
}
|
|
54
|
+
const openTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
55
|
+
const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);
|
|
56
|
+
handleError(timeoutError);
|
|
57
|
+
}, timeoutDuration);
|
|
58
|
+
function handleOpenSuccess() {
|
|
59
|
+
removeAllSocketListeners();
|
|
60
|
+
clearTimeout(openTimeout);
|
|
61
|
+
resolve();
|
|
62
|
+
}
|
|
63
|
+
socket.addEventListener("open", handleOpenSuccess);
|
|
64
|
+
socket.addEventListener("error", handleError);
|
|
65
|
+
socket.addEventListener("close", handleError);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
async function closeClientSocket(socket, options = {}) {
|
|
69
|
+
const { timeout: timeoutDuration } = options;
|
|
70
|
+
const isAlreadyClosed = socket.readyState === socket.CLOSED;
|
|
71
|
+
if (isAlreadyClosed) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await new Promise((resolve, reject) => {
|
|
75
|
+
function removeAllSocketListeners() {
|
|
76
|
+
socket.removeEventListener("error", handleError);
|
|
77
|
+
socket.removeEventListener("close", handleClose);
|
|
78
|
+
}
|
|
79
|
+
function handleError(error) {
|
|
80
|
+
removeAllSocketListeners();
|
|
81
|
+
reject(error);
|
|
82
|
+
}
|
|
83
|
+
const closeTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
84
|
+
const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);
|
|
85
|
+
handleError(timeoutError);
|
|
86
|
+
}, timeoutDuration);
|
|
87
|
+
function handleClose() {
|
|
88
|
+
removeAllSocketListeners();
|
|
89
|
+
clearTimeout(closeTimeout);
|
|
90
|
+
resolve();
|
|
91
|
+
}
|
|
92
|
+
socket.addEventListener("error", handleError);
|
|
93
|
+
socket.addEventListener("close", handleClose);
|
|
94
|
+
socket.close(options.code, options.reason);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/client/WebSocketClient.ts
|
|
99
|
+
var WebSocketClient = class _WebSocketClient {
|
|
100
|
+
constructor(_url, protocols) {
|
|
101
|
+
this._url = _url;
|
|
102
|
+
this.protocols = protocols;
|
|
103
|
+
}
|
|
104
|
+
socket;
|
|
105
|
+
_binaryType = "blob";
|
|
106
|
+
_onopen = null;
|
|
107
|
+
_onmessage = null;
|
|
108
|
+
_onclose = null;
|
|
109
|
+
_onerror = null;
|
|
110
|
+
listeners = {
|
|
111
|
+
open: /* @__PURE__ */ new Map(),
|
|
112
|
+
message: /* @__PURE__ */ new Map(),
|
|
113
|
+
close: /* @__PURE__ */ new Map(),
|
|
114
|
+
error: /* @__PURE__ */ new Map()
|
|
115
|
+
};
|
|
116
|
+
static CONNECTING = ClientSocket.CONNECTING;
|
|
117
|
+
get CONNECTING() {
|
|
118
|
+
return _WebSocketClient.CONNECTING;
|
|
119
|
+
}
|
|
120
|
+
static OPEN = ClientSocket.OPEN;
|
|
121
|
+
get OPEN() {
|
|
122
|
+
return _WebSocketClient.OPEN;
|
|
123
|
+
}
|
|
124
|
+
static CLOSING = ClientSocket.CLOSING;
|
|
125
|
+
get CLOSING() {
|
|
126
|
+
return _WebSocketClient.CLOSING;
|
|
127
|
+
}
|
|
128
|
+
static CLOSED = ClientSocket.CLOSED;
|
|
129
|
+
get CLOSED() {
|
|
130
|
+
return _WebSocketClient.CLOSED;
|
|
131
|
+
}
|
|
132
|
+
get binaryType() {
|
|
133
|
+
return this.socket?.binaryType ?? this._binaryType;
|
|
134
|
+
}
|
|
135
|
+
set binaryType(value) {
|
|
136
|
+
this._binaryType = value;
|
|
137
|
+
if (this.socket) {
|
|
138
|
+
this.socket.binaryType = value;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
get url() {
|
|
142
|
+
return this.socket?.url ?? this._url;
|
|
143
|
+
}
|
|
144
|
+
get protocol() {
|
|
145
|
+
return this.socket?.protocol ?? "";
|
|
146
|
+
}
|
|
147
|
+
get extensions() {
|
|
148
|
+
return this.socket?.extensions ?? "";
|
|
149
|
+
}
|
|
150
|
+
get readyState() {
|
|
151
|
+
return this.socket?.readyState ?? ClientSocket.CLOSED;
|
|
152
|
+
}
|
|
153
|
+
get bufferedAmount() {
|
|
154
|
+
return this.socket?.bufferedAmount ?? 0;
|
|
155
|
+
}
|
|
156
|
+
async open(options = {}) {
|
|
157
|
+
this.socket = new ClientSocket(this._url, this.protocols);
|
|
158
|
+
if (this.socket.binaryType !== this._binaryType) {
|
|
159
|
+
this.socket.binaryType = this._binaryType;
|
|
160
|
+
}
|
|
161
|
+
await openClientSocket(this.socket, options);
|
|
162
|
+
}
|
|
163
|
+
async close(code, reason, options = {}) {
|
|
164
|
+
if (!this.socket) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
await closeClientSocket(this.socket, { ...options, code, reason });
|
|
169
|
+
} finally {
|
|
170
|
+
this.onopen = null;
|
|
171
|
+
this.onmessage = null;
|
|
172
|
+
this.onclose = null;
|
|
173
|
+
this.onerror = null;
|
|
174
|
+
for (const [type, listenerToRawListener] of Object.entries(this.listeners)) {
|
|
175
|
+
for (const rawListener of listenerToRawListener.values()) {
|
|
176
|
+
this.socket.removeEventListener(type, rawListener);
|
|
177
|
+
}
|
|
178
|
+
listenerToRawListener.clear();
|
|
179
|
+
}
|
|
180
|
+
this.socket = void 0;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
send(data) {
|
|
184
|
+
this.socket?.send(data);
|
|
185
|
+
}
|
|
186
|
+
addEventListener(type, listener, options) {
|
|
187
|
+
const rawListener = listener.bind(this);
|
|
188
|
+
this.socket?.addEventListener(type, rawListener, options);
|
|
189
|
+
this.listeners[type].set(listener, rawListener);
|
|
190
|
+
}
|
|
191
|
+
removeEventListener(type, listener, options) {
|
|
192
|
+
const rawListener = this.listeners[type].get(listener);
|
|
193
|
+
if (rawListener) {
|
|
194
|
+
this.socket?.removeEventListener(type, rawListener, options);
|
|
195
|
+
this.listeners[type].delete(listener);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
get onopen() {
|
|
199
|
+
return this._onopen;
|
|
200
|
+
}
|
|
201
|
+
set onopen(listener) {
|
|
202
|
+
this.setUnitaryEventListener("open", listener);
|
|
203
|
+
}
|
|
204
|
+
get onmessage() {
|
|
205
|
+
return this._onmessage;
|
|
206
|
+
}
|
|
207
|
+
set onmessage(listener) {
|
|
208
|
+
this.setUnitaryEventListener("message", listener);
|
|
209
|
+
}
|
|
210
|
+
get onclose() {
|
|
211
|
+
return this._onclose;
|
|
212
|
+
}
|
|
213
|
+
set onclose(listener) {
|
|
214
|
+
this.setUnitaryEventListener("close", listener);
|
|
215
|
+
}
|
|
216
|
+
get onerror() {
|
|
217
|
+
return this._onerror;
|
|
218
|
+
}
|
|
219
|
+
set onerror(listener) {
|
|
220
|
+
this.setUnitaryEventListener("error", listener);
|
|
221
|
+
}
|
|
222
|
+
setUnitaryEventListener(type, listener) {
|
|
223
|
+
if (listener) {
|
|
224
|
+
const rawListener = listener.bind(this);
|
|
225
|
+
this.listeners[type].set(listener, rawListener);
|
|
226
|
+
if (this.socket) {
|
|
227
|
+
this.socket[`on${type}`] = rawListener;
|
|
228
|
+
}
|
|
229
|
+
this[`_on${type}`] = listener;
|
|
230
|
+
} else {
|
|
231
|
+
const currentListener = this[`_on${type}`];
|
|
232
|
+
if (currentListener) {
|
|
233
|
+
this.listeners[type].delete(currentListener);
|
|
234
|
+
}
|
|
235
|
+
if (this.socket) {
|
|
236
|
+
this.socket[`on${type}`] = null;
|
|
237
|
+
}
|
|
238
|
+
this[`_on${type}`] = null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
dispatchEvent(event) {
|
|
242
|
+
return this.socket?.dispatchEvent(event) ?? false;
|
|
243
|
+
}
|
|
244
|
+
};
|
|
245
|
+
var WebSocketClient_default = WebSocketClient;
|
|
246
|
+
|
|
247
|
+
export { WebSocketClient_default as WebSocketClient, WebSocketCloseTimeoutError, WebSocketMessageAbortError, WebSocketOpenTimeoutError, WebSocketTimeoutError };
|
|
248
|
+
//# sourceMappingURL=index.mjs.map
|
|
249
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketMessageAbortError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/client/ClientSocket.ts","../src/client/utils/lifecycle.ts","../src/client/WebSocketClient.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketMessageAbortError extends WebSocketTimeoutError {\n constructor() {\n super('Web socket message was aborted.');\n this.name = 'WebSocketMessageAbortError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import NodeWebSocket from 'ws';\n\n// WebSocket is available natively in browsers and Node.js >=22.\nconst isNativeWebSocketAvailable = typeof WebSocket !== 'undefined';\n\nexport const ClientSocket = (isNativeWebSocketAvailable ? WebSocket : NodeWebSocket) as typeof WebSocket;\nexport type ClientSocket = InstanceType<typeof ClientSocket>;\n","import { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nimport { ClientSocket } from '../ClientSocket';\n\nexport async function openClientSocket(socket: ClientSocket, options: { timeout?: number } = {}) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyOpen = socket.readyState === socket.OPEN;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n function removeAllSocketListeners() {\n socket.removeEventListener('open', handleOpenSuccess); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeAllSocketListeners();\n reject(error);\n }\n\n const openTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n handleError(timeoutError);\n }, timeoutDuration);\n\n function handleOpenSuccess() {\n removeAllSocketListeners();\n clearTimeout(openTimeout);\n resolve();\n }\n\n socket.addEventListener('open', handleOpenSuccess);\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleError);\n });\n}\n\nexport async function closeClientSocket(\n socket: ClientSocket,\n options: { code?: number; reason?: string; timeout?: number } = {},\n) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyClosed = socket.readyState === socket.CLOSED;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n function removeAllSocketListeners() {\n socket.removeEventListener('error', handleError); // eslint-disable-line @typescript-eslint/no-use-before-define\n socket.removeEventListener('close', handleClose); // eslint-disable-line @typescript-eslint/no-use-before-define\n }\n\n function handleError(error: unknown) {\n removeAllSocketListeners();\n reject(error);\n }\n\n const closeTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n handleError(timeoutError);\n }, timeoutDuration);\n\n function handleClose() {\n removeAllSocketListeners();\n clearTimeout(closeTimeout);\n resolve();\n }\n\n socket.addEventListener('error', handleError);\n socket.addEventListener('close', handleClose);\n\n socket.close(options.code, options.reason);\n });\n}\n","import { WebSocketEvent, WebSocketEventType, WebSocketMessageData, WebSocketSchema } from '@/types/schema';\n\nimport { ClientSocket } from './ClientSocket';\nimport { closeClientSocket, openClientSocket } from './utils/lifecycle';\n\nexport type WebSocketClientEventListener<Schema extends WebSocketSchema, Type extends WebSocketEventType<Schema>> = (\n this: WebSocketClient<Schema>,\n event: WebSocketEvent<Schema, Type>,\n) => unknown;\n\ntype WebSocketClientRawEventListener = (this: ClientSocket, event: Event) => unknown;\n\nclass WebSocketClient<Schema extends WebSocketSchema> implements Omit<\n WebSocket,\n `${string}EventListener` | `on${string}`\n> {\n private socket?: ClientSocket;\n private _binaryType: BinaryType = 'blob';\n\n private _onopen: WebSocketClientEventListener<Schema, 'open'> | null = null;\n private _onmessage: WebSocketClientEventListener<Schema, 'message'> | null = null;\n private _onclose: WebSocketClientEventListener<Schema, 'close'> | null = null;\n private _onerror: WebSocketClientEventListener<Schema, 'error'> | null = null;\n\n private listeners: {\n [Type in WebSocketEventType<Schema>]: Map<\n WebSocketClientEventListener<Schema, Type>,\n WebSocketClientRawEventListener\n >;\n } = {\n open: new Map(),\n message: new Map(),\n close: new Map(),\n error: new Map(),\n };\n\n constructor(\n private _url: string,\n private protocols?: string | string[],\n ) {}\n\n static CONNECTING = ClientSocket.CONNECTING;\n\n get CONNECTING() {\n return WebSocketClient.CONNECTING;\n }\n\n static OPEN = ClientSocket.OPEN;\n\n get OPEN() {\n return WebSocketClient.OPEN;\n }\n\n static CLOSING = ClientSocket.CLOSING;\n\n get CLOSING() {\n return WebSocketClient.CLOSING;\n }\n\n static CLOSED = ClientSocket.CLOSED;\n\n get CLOSED() {\n return WebSocketClient.CLOSED;\n }\n\n get binaryType() {\n return this.socket?.binaryType ?? this._binaryType;\n }\n\n set binaryType(value: 'blob' | 'arraybuffer') {\n this._binaryType = value;\n\n if (this.socket) {\n this.socket.binaryType = value;\n }\n }\n\n get url() {\n return this.socket?.url ?? this._url;\n }\n\n get protocol() {\n return this.socket?.protocol ?? '';\n }\n\n get extensions() {\n return this.socket?.extensions ?? '';\n }\n\n get readyState() {\n return this.socket?.readyState ?? ClientSocket.CLOSED;\n }\n\n get bufferedAmount() {\n return this.socket?.bufferedAmount ?? 0;\n }\n\n async open(options: { timeout?: number } = {}) {\n this.socket = new ClientSocket(this._url, this.protocols);\n\n if (this.socket.binaryType !== this._binaryType) {\n this.socket.binaryType = this._binaryType;\n }\n\n await openClientSocket(this.socket, options);\n }\n\n async close(code?: number, reason?: string, options: { timeout?: number } = {}) {\n if (!this.socket) {\n return;\n }\n\n try {\n await closeClientSocket(this.socket, { ...options, code, reason });\n } finally {\n this.onopen = null;\n this.onmessage = null;\n this.onclose = null;\n this.onerror = null;\n\n for (const [type, listenerToRawListener] of Object.entries(this.listeners)) {\n for (const rawListener of listenerToRawListener.values()) {\n this.socket.removeEventListener(type, rawListener);\n }\n\n listenerToRawListener.clear();\n }\n\n this.socket = undefined;\n }\n }\n\n send(data: WebSocketMessageData<Schema>) {\n this.socket?.send(data);\n }\n\n addEventListener<Type extends WebSocketEventType<Schema>>(\n type: Type,\n listener: (this: WebSocketClient<Schema>, event: WebSocketEvent<Schema, Type>) => unknown,\n options?: boolean | AddEventListenerOptions,\n ) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n\n this.socket?.addEventListener(type, rawListener, options);\n this.listeners[type].set(listener, rawListener);\n }\n\n removeEventListener<Type extends WebSocketEventType<Schema>>(\n type: Type,\n listener: (this: WebSocketClient<Schema>, event: WebSocketEvent<Schema, Type>) => unknown,\n options?: boolean | EventListenerOptions,\n ) {\n const rawListener = this.listeners[type].get(listener);\n\n if (rawListener) {\n this.socket?.removeEventListener(type, rawListener, options);\n this.listeners[type].delete(listener);\n }\n }\n\n get onopen() {\n return this._onopen;\n }\n\n set onopen(listener: WebSocketClientEventListener<Schema, 'open'> | null) {\n this.setUnitaryEventListener('open', listener);\n }\n\n get onmessage() {\n return this._onmessage;\n }\n\n set onmessage(listener: WebSocketClientEventListener<Schema, 'message'> | null) {\n this.setUnitaryEventListener('message', listener);\n }\n\n get onclose() {\n return this._onclose;\n }\n\n set onclose(listener: WebSocketClientEventListener<Schema, 'close'> | null) {\n this.setUnitaryEventListener('close', listener);\n }\n\n get onerror() {\n return this._onerror;\n }\n\n set onerror(listener: WebSocketClientEventListener<Schema, 'error'> | null) {\n this.setUnitaryEventListener('error', listener);\n }\n\n private setUnitaryEventListener<Type extends WebSocketEventType<Schema>>(\n type: Type,\n listener: WebSocketClientEventListener<Schema, Type> | null,\n ) {\n type PrivateUnitaryListener = typeof listener;\n\n if (listener) {\n const rawListener = listener.bind(this) as WebSocketClientRawEventListener;\n this.listeners[type].set(listener, rawListener);\n\n if (this.socket) {\n this.socket[`on${type}`] = rawListener;\n }\n\n (this[`_on${type}`] as PrivateUnitaryListener) = listener;\n } else {\n const currentListener = this[`_on${type}`] as PrivateUnitaryListener;\n\n if (currentListener) {\n this.listeners[type].delete(currentListener);\n }\n\n if (this.socket) {\n this.socket[`on${type}`] = null;\n }\n\n (this[`_on${type}`] as PrivateUnitaryListener) = null;\n }\n }\n\n dispatchEvent<Type extends WebSocketEventType<Schema>>(event: WebSocketEvent<Schema, Type>) {\n return this.socket?.dispatchEvent(event) ?? false;\n }\n}\n\nexport default WebSocketClient;\n"]}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Server } from 'http';
|
|
2
|
+
import { Server as Server$1 } from 'https';
|
|
3
|
+
|
|
4
|
+
interface WebSocketServerOptions {
|
|
5
|
+
server: Server | Server$1;
|
|
6
|
+
}
|
|
7
|
+
declare class WebSocketServer {
|
|
8
|
+
private server;
|
|
9
|
+
private socket;
|
|
10
|
+
private isSocketOpen;
|
|
11
|
+
constructor(options: WebSocketServerOptions);
|
|
12
|
+
get isRunning(): boolean;
|
|
13
|
+
start(options?: {
|
|
14
|
+
timeout?: number;
|
|
15
|
+
}): Promise<void>;
|
|
16
|
+
stop(options?: {
|
|
17
|
+
timeout?: number;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { WebSocketServer, type WebSocketServerOptions };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var ws = require('ws');
|
|
4
|
+
|
|
5
|
+
// src/server/ServerSocket.ts
|
|
6
|
+
|
|
7
|
+
// src/errors/WebSocketTimeoutError.ts
|
|
8
|
+
var WebSocketTimeoutError = class extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "WebSocketTimeoutError";
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
// src/errors/WebSocketCloseTimeoutError.ts
|
|
16
|
+
var WebSocketCloseTimeoutError = class extends WebSocketTimeoutError {
|
|
17
|
+
constructor(reachedTimeout) {
|
|
18
|
+
super(`Web socket close timed out after ${reachedTimeout}ms.`);
|
|
19
|
+
this.name = "WebSocketCloseTimeoutError";
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// src/errors/WebSocketOpenTimeoutError.ts
|
|
24
|
+
var WebSocketOpenTimeoutError = class extends WebSocketTimeoutError {
|
|
25
|
+
constructor(reachedTimeout) {
|
|
26
|
+
super(`Web socket open timed out after ${reachedTimeout}ms.`);
|
|
27
|
+
this.name = "WebSocketOpenTimeoutError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// src/server/utils/lifecycle.ts
|
|
32
|
+
async function openServerSocket(server, socket, options = {}) {
|
|
33
|
+
const { timeout: timeoutDuration } = options;
|
|
34
|
+
const isAlreadyOpen = server.listening;
|
|
35
|
+
if (isAlreadyOpen) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
await new Promise((resolve, reject) => {
|
|
39
|
+
const openTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
40
|
+
const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);
|
|
41
|
+
reject(timeoutError);
|
|
42
|
+
}, timeoutDuration);
|
|
43
|
+
socket.once("listening", () => {
|
|
44
|
+
clearTimeout(openTimeout);
|
|
45
|
+
resolve();
|
|
46
|
+
});
|
|
47
|
+
socket.once("error", (error) => {
|
|
48
|
+
clearTimeout(openTimeout);
|
|
49
|
+
reject(error);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async function closeServerSocket(server, socket, options = {}) {
|
|
54
|
+
const { timeout: timeoutDuration } = options;
|
|
55
|
+
const isAlreadyClosed = !server.listening;
|
|
56
|
+
if (isAlreadyClosed) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
await new Promise((resolve, reject) => {
|
|
60
|
+
const closeTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
61
|
+
const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);
|
|
62
|
+
reject(timeoutError);
|
|
63
|
+
}, timeoutDuration);
|
|
64
|
+
for (const client of socket.clients) {
|
|
65
|
+
client.close();
|
|
66
|
+
}
|
|
67
|
+
socket.close((error) => {
|
|
68
|
+
clearTimeout(closeTimeout);
|
|
69
|
+
if (error) {
|
|
70
|
+
reject(error);
|
|
71
|
+
} else {
|
|
72
|
+
resolve();
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// src/server/WebSocketServer.ts
|
|
79
|
+
var WebSocketServer2 = class {
|
|
80
|
+
server;
|
|
81
|
+
socket;
|
|
82
|
+
isSocketOpen;
|
|
83
|
+
constructor(options) {
|
|
84
|
+
this.server = options.server;
|
|
85
|
+
this.socket = new ws.WebSocketServer({ server: options.server });
|
|
86
|
+
this.isSocketOpen = options.server.listening;
|
|
87
|
+
}
|
|
88
|
+
get isRunning() {
|
|
89
|
+
return this.server.listening && this.isSocketOpen;
|
|
90
|
+
}
|
|
91
|
+
async start(options = {}) {
|
|
92
|
+
if (this.isSocketOpen) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
await openServerSocket(this.server, this.socket, options);
|
|
96
|
+
this.isSocketOpen = true;
|
|
97
|
+
}
|
|
98
|
+
async stop(options = {}) {
|
|
99
|
+
if (!this.isSocketOpen) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
await closeServerSocket(this.server, this.socket, options);
|
|
103
|
+
this.isSocketOpen = false;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
var WebSocketServer_default = WebSocketServer2;
|
|
107
|
+
/* istanbul ignore if -- @preserve
|
|
108
|
+
* This is not expected since the server is not stopped unless it is running. */
|
|
109
|
+
|
|
110
|
+
exports.WebSocketServer = WebSocketServer_default;
|
|
111
|
+
//# sourceMappingURL=server.js.map
|
|
112
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["WebSocketServer"],"mappings":"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","file":"server.js","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\n\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nimport { ServerSocket } from '../ServerSocket';\n\nexport async function openServerSocket(\n server: HttpServer | HttpsServer,\n socket: ServerSocket,\n options: { timeout?: number } = {},\n) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyOpen = server.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n socket.once('listening', () => {\n clearTimeout(openTimeout);\n resolve();\n });\n\n socket.once('error', (error) => {\n clearTimeout(openTimeout);\n reject(error);\n });\n });\n}\n\nexport async function closeServerSocket(\n server: HttpServer | HttpsServer,\n socket: ServerSocket,\n options: { timeout?: number } = {},\n) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyClosed = !server.listening;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of socket.clients) {\n client.close();\n }\n\n socket.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\n\nimport { ServerSocket } from './ServerSocket';\nimport { closeServerSocket, openServerSocket } from './utils/lifecycle';\n\nexport interface WebSocketServerOptions {\n server: HttpServer | HttpsServer;\n}\n\nclass WebSocketServer {\n private server: HttpServer | HttpsServer;\n private socket: ServerSocket;\n private isSocketOpen: boolean;\n\n constructor(options: WebSocketServerOptions) {\n this.server = options.server;\n this.socket = new ServerSocket({ server: options.server });\n this.isSocketOpen = options.server.listening;\n }\n\n get isRunning() {\n return this.server.listening && this.isSocketOpen;\n }\n\n async start(options: { timeout?: number } = {}) {\n if (this.isSocketOpen) {\n return;\n }\n\n await openServerSocket(this.server, this.socket, options);\n this.isSocketOpen = true;\n }\n\n async stop(options: { timeout?: number } = {}) {\n if (!this.isSocketOpen) {\n return;\n }\n\n await closeServerSocket(this.server, this.socket, options);\n this.isSocketOpen = false;\n }\n}\n\nexport default WebSocketServer;\n"]}
|
package/dist/server.mjs
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { WebSocketServer } from 'ws';
|
|
2
|
+
|
|
3
|
+
// src/server/ServerSocket.ts
|
|
4
|
+
|
|
5
|
+
// src/errors/WebSocketTimeoutError.ts
|
|
6
|
+
var WebSocketTimeoutError = class extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "WebSocketTimeoutError";
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/errors/WebSocketCloseTimeoutError.ts
|
|
14
|
+
var WebSocketCloseTimeoutError = class extends WebSocketTimeoutError {
|
|
15
|
+
constructor(reachedTimeout) {
|
|
16
|
+
super(`Web socket close timed out after ${reachedTimeout}ms.`);
|
|
17
|
+
this.name = "WebSocketCloseTimeoutError";
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// src/errors/WebSocketOpenTimeoutError.ts
|
|
22
|
+
var WebSocketOpenTimeoutError = class extends WebSocketTimeoutError {
|
|
23
|
+
constructor(reachedTimeout) {
|
|
24
|
+
super(`Web socket open timed out after ${reachedTimeout}ms.`);
|
|
25
|
+
this.name = "WebSocketOpenTimeoutError";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/server/utils/lifecycle.ts
|
|
30
|
+
async function openServerSocket(server, socket, options = {}) {
|
|
31
|
+
const { timeout: timeoutDuration } = options;
|
|
32
|
+
const isAlreadyOpen = server.listening;
|
|
33
|
+
if (isAlreadyOpen) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
const openTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
38
|
+
const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);
|
|
39
|
+
reject(timeoutError);
|
|
40
|
+
}, timeoutDuration);
|
|
41
|
+
socket.once("listening", () => {
|
|
42
|
+
clearTimeout(openTimeout);
|
|
43
|
+
resolve();
|
|
44
|
+
});
|
|
45
|
+
socket.once("error", (error) => {
|
|
46
|
+
clearTimeout(openTimeout);
|
|
47
|
+
reject(error);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async function closeServerSocket(server, socket, options = {}) {
|
|
52
|
+
const { timeout: timeoutDuration } = options;
|
|
53
|
+
const isAlreadyClosed = !server.listening;
|
|
54
|
+
if (isAlreadyClosed) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
await new Promise((resolve, reject) => {
|
|
58
|
+
const closeTimeout = timeoutDuration === void 0 ? void 0 : setTimeout(() => {
|
|
59
|
+
const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);
|
|
60
|
+
reject(timeoutError);
|
|
61
|
+
}, timeoutDuration);
|
|
62
|
+
for (const client of socket.clients) {
|
|
63
|
+
client.close();
|
|
64
|
+
}
|
|
65
|
+
socket.close((error) => {
|
|
66
|
+
clearTimeout(closeTimeout);
|
|
67
|
+
if (error) {
|
|
68
|
+
reject(error);
|
|
69
|
+
} else {
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/server/WebSocketServer.ts
|
|
77
|
+
var WebSocketServer2 = class {
|
|
78
|
+
server;
|
|
79
|
+
socket;
|
|
80
|
+
isSocketOpen;
|
|
81
|
+
constructor(options) {
|
|
82
|
+
this.server = options.server;
|
|
83
|
+
this.socket = new WebSocketServer({ server: options.server });
|
|
84
|
+
this.isSocketOpen = options.server.listening;
|
|
85
|
+
}
|
|
86
|
+
get isRunning() {
|
|
87
|
+
return this.server.listening && this.isSocketOpen;
|
|
88
|
+
}
|
|
89
|
+
async start(options = {}) {
|
|
90
|
+
if (this.isSocketOpen) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await openServerSocket(this.server, this.socket, options);
|
|
94
|
+
this.isSocketOpen = true;
|
|
95
|
+
}
|
|
96
|
+
async stop(options = {}) {
|
|
97
|
+
if (!this.isSocketOpen) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
await closeServerSocket(this.server, this.socket, options);
|
|
101
|
+
this.isSocketOpen = false;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var WebSocketServer_default = WebSocketServer2;
|
|
105
|
+
/* istanbul ignore if -- @preserve
|
|
106
|
+
* This is not expected since the server is not stopped unless it is running. */
|
|
107
|
+
|
|
108
|
+
export { WebSocketServer_default as WebSocketServer };
|
|
109
|
+
//# sourceMappingURL=server.mjs.map
|
|
110
|
+
//# sourceMappingURL=server.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors/WebSocketTimeoutError.ts","../src/errors/WebSocketCloseTimeoutError.ts","../src/errors/WebSocketOpenTimeoutError.ts","../src/server/utils/lifecycle.ts","../src/server/WebSocketServer.ts"],"names":["WebSocketServer"],"mappings":"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","file":"server.mjs","sourcesContent":["export class WebSocketTimeoutError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'WebSocketTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketCloseTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket close timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketCloseTimeoutError';\n }\n}\n","import { WebSocketTimeoutError } from './WebSocketTimeoutError';\n\nexport class WebSocketOpenTimeoutError extends WebSocketTimeoutError {\n constructor(reachedTimeout: number) {\n super(`Web socket open timed out after ${reachedTimeout}ms.`);\n this.name = 'WebSocketOpenTimeoutError';\n }\n}\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\n\nimport { WebSocketCloseTimeoutError } from '@/errors/WebSocketCloseTimeoutError';\nimport { WebSocketOpenTimeoutError } from '@/errors/WebSocketOpenTimeoutError';\n\nimport { ServerSocket } from '../ServerSocket';\n\nexport async function openServerSocket(\n server: HttpServer | HttpsServer,\n socket: ServerSocket,\n options: { timeout?: number } = {},\n) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyOpen = server.listening;\n\n if (isAlreadyOpen) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const openTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketOpenTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n socket.once('listening', () => {\n clearTimeout(openTimeout);\n resolve();\n });\n\n socket.once('error', (error) => {\n clearTimeout(openTimeout);\n reject(error);\n });\n });\n}\n\nexport async function closeServerSocket(\n server: HttpServer | HttpsServer,\n socket: ServerSocket,\n options: { timeout?: number } = {},\n) {\n const { timeout: timeoutDuration } = options;\n\n const isAlreadyClosed = !server.listening;\n\n if (isAlreadyClosed) {\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n const closeTimeout =\n timeoutDuration === undefined\n ? undefined\n : setTimeout(() => {\n const timeoutError = new WebSocketCloseTimeoutError(timeoutDuration);\n reject(timeoutError);\n }, timeoutDuration);\n\n for (const client of socket.clients) {\n client.close();\n }\n\n socket.close((error) => {\n clearTimeout(closeTimeout);\n\n /* istanbul ignore if -- @preserve\n * This is not expected since the server is not stopped unless it is running. */\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n });\n}\n","import { Server as HttpServer } from 'http';\nimport { Server as HttpsServer } from 'https';\n\nimport { ServerSocket } from './ServerSocket';\nimport { closeServerSocket, openServerSocket } from './utils/lifecycle';\n\nexport interface WebSocketServerOptions {\n server: HttpServer | HttpsServer;\n}\n\nclass WebSocketServer {\n private server: HttpServer | HttpsServer;\n private socket: ServerSocket;\n private isSocketOpen: boolean;\n\n constructor(options: WebSocketServerOptions) {\n this.server = options.server;\n this.socket = new ServerSocket({ server: options.server });\n this.isSocketOpen = options.server.listening;\n }\n\n get isRunning() {\n return this.server.listening && this.isSocketOpen;\n }\n\n async start(options: { timeout?: number } = {}) {\n if (this.isSocketOpen) {\n return;\n }\n\n await openServerSocket(this.server, this.socket, options);\n this.isSocketOpen = true;\n }\n\n async stop(options: { timeout?: number } = {}) {\n if (!this.isSocketOpen) {\n return;\n }\n\n await closeServerSocket(this.server, this.socket, options);\n this.isSocketOpen = false;\n }\n}\n\nexport default WebSocketServer;\n"]}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './dist';
|