@culpeo/async-ws 0.2.0 → 1.1.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/CHANGELOG.md +24 -1
- package/README.md +162 -3
- package/dist/browser/index.js +219 -15
- package/dist/cjs/index.cjs +231 -14
- package/dist/esm/index.js +231 -14
- package/dist/iife/index.js +219 -15
- package/dist/index.d.ts +63 -1
- package/package.json +8 -5
package/dist/iife/index.js
CHANGED
|
@@ -13,7 +13,17 @@ var AsyncWS = (function (exports) {
|
|
|
13
13
|
return Promise.reject(new Error("WebSocket is not open"));
|
|
14
14
|
}
|
|
15
15
|
try {
|
|
16
|
-
|
|
16
|
+
if (ArrayBuffer.isView(data)) {
|
|
17
|
+
if (data.buffer instanceof SharedArrayBuffer) {
|
|
18
|
+
throw new Error("SharedArrayBuffer-backed views are not supported. " +
|
|
19
|
+
"Copy into a regular ArrayBuffer before sending.");
|
|
20
|
+
}
|
|
21
|
+
// Zero-copy: create a Uint8Array view over the same ArrayBuffer
|
|
22
|
+
socket.send(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
socket.send(data);
|
|
26
|
+
}
|
|
17
27
|
return Promise.resolve();
|
|
18
28
|
}
|
|
19
29
|
catch (err) {
|
|
@@ -45,6 +55,19 @@ var AsyncWS = (function (exports) {
|
|
|
45
55
|
function socketClose(socket, code, reason) {
|
|
46
56
|
socket.close(code, reason);
|
|
47
57
|
}
|
|
58
|
+
function socketTerminate(socket) {
|
|
59
|
+
socket.close();
|
|
60
|
+
}
|
|
61
|
+
function socketPing(_socket) {
|
|
62
|
+
throw new Error("Ping is not supported in browsers.");
|
|
63
|
+
}
|
|
64
|
+
function attachPongListener(_socket, _onPong) {
|
|
65
|
+
return () => { };
|
|
66
|
+
}
|
|
67
|
+
function adoptSocket(_rawSocket) {
|
|
68
|
+
throw new Error("fromSocket() is not supported in browsers. " +
|
|
69
|
+
"Browsers cannot accept server-side WebSocket connections.");
|
|
70
|
+
}
|
|
48
71
|
|
|
49
72
|
/**
|
|
50
73
|
* Imperative WebSocket client that works in both browser and Node.js.
|
|
@@ -65,7 +88,71 @@ var AsyncWS = (function (exports) {
|
|
|
65
88
|
this.terminalError = null;
|
|
66
89
|
this.closeInfo = null;
|
|
67
90
|
this.removeListeners = null;
|
|
91
|
+
this.keepAliveTimer = null;
|
|
92
|
+
this.pongTimer = null;
|
|
93
|
+
this.removePongListener = null;
|
|
94
|
+
this.connectionId = 0;
|
|
68
95
|
this.maxBufferSize = options?.maxBufferSize ?? 0;
|
|
96
|
+
if (options?.keepAlive) {
|
|
97
|
+
{
|
|
98
|
+
throw new Error("keepAlive is not supported in browsers. " +
|
|
99
|
+
"The browser handles WebSocket ping/pong at the protocol level automatically.");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Adopt an already-open WebSocket (e.g. from a `WebSocketServer` connection event).
|
|
105
|
+
*
|
|
106
|
+
* Returns a `WebSocketClient` in the "open" state, ready to send/receive.
|
|
107
|
+
* The client takes ownership of the socket lifecycle: calling `close()`
|
|
108
|
+
* will close the underlying socket.
|
|
109
|
+
*
|
|
110
|
+
* **Node.js only.** Throws in browser builds.
|
|
111
|
+
*
|
|
112
|
+
* Call this immediately in the server's `connection` handler to avoid
|
|
113
|
+
* missing messages:
|
|
114
|
+
*
|
|
115
|
+
* ```ts
|
|
116
|
+
* wss.on("connection", (socket) => {
|
|
117
|
+
* const client = WebSocketClient.fromSocket(socket);
|
|
118
|
+
* const msg = await client.receive();
|
|
119
|
+
* });
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
static fromSocket(rawSocket, options) {
|
|
123
|
+
const client = new WebSocketClient(options);
|
|
124
|
+
const socket = adoptSocket();
|
|
125
|
+
client.socket = socket;
|
|
126
|
+
setBinaryType(socket);
|
|
127
|
+
client.state = "open";
|
|
128
|
+
const currentConnectionId = ++client.connectionId;
|
|
129
|
+
client.removeListeners = attachListeners(socket,
|
|
130
|
+
// onOpen — already open, won't fire
|
|
131
|
+
() => { },
|
|
132
|
+
// onMessage
|
|
133
|
+
(data, binary) => {
|
|
134
|
+
client.enqueueMessage({ data, binary });
|
|
135
|
+
},
|
|
136
|
+
// onClose
|
|
137
|
+
(code, reason, wasClean) => {
|
|
138
|
+
if (currentConnectionId !== client.connectionId)
|
|
139
|
+
return;
|
|
140
|
+
client.closeInfo = { code, reason, wasClean };
|
|
141
|
+
client.state = "closed";
|
|
142
|
+
client.cleanup();
|
|
143
|
+
if (client.buffer.length === 0) {
|
|
144
|
+
client.rejectAllWaiters(new Error(`WebSocket closed (code: ${code}, reason: ${reason})`));
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
// onError
|
|
148
|
+
(error) => {
|
|
149
|
+
if (currentConnectionId !== client.connectionId)
|
|
150
|
+
return;
|
|
151
|
+
client.terminalError = error;
|
|
152
|
+
client.rejectAllWaiters(error);
|
|
153
|
+
});
|
|
154
|
+
client.startKeepAlive();
|
|
155
|
+
return client;
|
|
69
156
|
}
|
|
70
157
|
/** Current connection state. */
|
|
71
158
|
get readyState() {
|
|
@@ -75,16 +162,41 @@ var AsyncWS = (function (exports) {
|
|
|
75
162
|
get lastCloseInfo() {
|
|
76
163
|
return this.closeInfo;
|
|
77
164
|
}
|
|
165
|
+
/** The negotiated subprotocol, or empty string if none. */
|
|
166
|
+
get protocol() {
|
|
167
|
+
return this.socket?.protocol ?? "";
|
|
168
|
+
}
|
|
169
|
+
/** The URL of the WebSocket connection. */
|
|
170
|
+
get url() {
|
|
171
|
+
return this.socket?.url ?? "";
|
|
172
|
+
}
|
|
173
|
+
/** The number of bytes of data queued for sending. */
|
|
174
|
+
get bufferedAmount() {
|
|
175
|
+
return this.socket?.bufferedAmount ?? 0;
|
|
176
|
+
}
|
|
177
|
+
/** The extensions negotiated by the server. */
|
|
178
|
+
get extensions() {
|
|
179
|
+
return this.socket?.extensions ?? "";
|
|
180
|
+
}
|
|
78
181
|
/**
|
|
79
182
|
* Connect to a WebSocket server.
|
|
80
183
|
* Resolves when the connection is open. Rejects on error.
|
|
81
184
|
*/
|
|
82
185
|
connect(url, options) {
|
|
83
|
-
if (this.state !== "idle" &&
|
|
186
|
+
if (this.state !== "idle" &&
|
|
187
|
+
this.state !== "closed" &&
|
|
188
|
+
this.state !== "errored") {
|
|
84
189
|
return Promise.reject(new Error(`Cannot connect: client is in "${this.state}" state`));
|
|
85
190
|
}
|
|
191
|
+
if (options?.timeout !== undefined && options.timeout <= 0) {
|
|
192
|
+
return Promise.reject(new Error("timeout must be greater than 0."));
|
|
193
|
+
}
|
|
194
|
+
if (options?.signal?.aborted) {
|
|
195
|
+
return Promise.reject(new Error("Connection aborted."));
|
|
196
|
+
}
|
|
86
197
|
this.reset();
|
|
87
198
|
this.state = "connecting";
|
|
199
|
+
const currentConnectionId = ++this.connectionId;
|
|
88
200
|
return new Promise((resolve, reject) => {
|
|
89
201
|
try {
|
|
90
202
|
this.socket = createWebSocket(url, options);
|
|
@@ -92,19 +204,63 @@ var AsyncWS = (function (exports) {
|
|
|
92
204
|
}
|
|
93
205
|
catch (err) {
|
|
94
206
|
this.state = "errored";
|
|
95
|
-
this.terminalError =
|
|
207
|
+
this.terminalError =
|
|
208
|
+
err instanceof Error ? err : new Error(String(err));
|
|
96
209
|
reject(this.terminalError);
|
|
97
210
|
return;
|
|
98
211
|
}
|
|
99
212
|
let settled = false;
|
|
213
|
+
let timeoutId = null;
|
|
214
|
+
const settle = (fn) => {
|
|
215
|
+
if (settled)
|
|
216
|
+
return;
|
|
217
|
+
settled = true;
|
|
218
|
+
if (timeoutId !== null) {
|
|
219
|
+
clearTimeout(timeoutId);
|
|
220
|
+
timeoutId = null;
|
|
221
|
+
}
|
|
222
|
+
if (options?.signal) {
|
|
223
|
+
options.signal.removeEventListener("abort", onAbort);
|
|
224
|
+
}
|
|
225
|
+
fn();
|
|
226
|
+
};
|
|
227
|
+
const onAbort = () => {
|
|
228
|
+
settle(() => {
|
|
229
|
+
this.state = "closed";
|
|
230
|
+
this.terminalError = new Error("Connection aborted.");
|
|
231
|
+
if (this.socket) {
|
|
232
|
+
socketTerminate(this.socket);
|
|
233
|
+
}
|
|
234
|
+
// Don't call cleanup() here — socketTerminate() emits
|
|
235
|
+
// error/close asynchronously; let onClose handle cleanup.
|
|
236
|
+
reject(this.terminalError);
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
if (options?.timeout !== undefined) {
|
|
240
|
+
timeoutId = setTimeout(() => {
|
|
241
|
+
settle(() => {
|
|
242
|
+
this.state = "closed";
|
|
243
|
+
this.terminalError = new Error(`Connection timed out after ${options.timeout}ms.`);
|
|
244
|
+
if (this.socket) {
|
|
245
|
+
socketTerminate(this.socket);
|
|
246
|
+
}
|
|
247
|
+
// Don't call cleanup() here — socketTerminate() emits
|
|
248
|
+
// error/close asynchronously; let onClose handle cleanup.
|
|
249
|
+
reject(this.terminalError);
|
|
250
|
+
});
|
|
251
|
+
}, options.timeout);
|
|
252
|
+
}
|
|
253
|
+
if (options?.signal) {
|
|
254
|
+
options.signal.addEventListener("abort", onAbort, { once: true });
|
|
255
|
+
}
|
|
100
256
|
this.removeListeners = attachListeners(this.socket,
|
|
101
257
|
// onOpen
|
|
102
258
|
() => {
|
|
103
|
-
|
|
104
|
-
settled = true;
|
|
259
|
+
settle(() => {
|
|
105
260
|
this.state = "open";
|
|
261
|
+
this.startKeepAlive();
|
|
106
262
|
resolve();
|
|
107
|
-
}
|
|
263
|
+
});
|
|
108
264
|
},
|
|
109
265
|
// onMessage
|
|
110
266
|
(data, binary) => {
|
|
@@ -112,14 +268,16 @@ var AsyncWS = (function (exports) {
|
|
|
112
268
|
},
|
|
113
269
|
// onClose
|
|
114
270
|
(code, reason, wasClean) => {
|
|
271
|
+
// Ignore close events from a stale connection (e.g., after
|
|
272
|
+
// timeout/abort triggered a reconnect on the same client).
|
|
273
|
+
if (currentConnectionId !== this.connectionId)
|
|
274
|
+
return;
|
|
115
275
|
this.closeInfo = { code, reason, wasClean };
|
|
116
|
-
this.state;
|
|
117
276
|
this.state = "closed";
|
|
118
277
|
this.cleanup();
|
|
119
|
-
|
|
120
|
-
settled = true;
|
|
278
|
+
settle(() => {
|
|
121
279
|
reject(new Error(`WebSocket closed before opening (code: ${code}, reason: ${reason})`));
|
|
122
|
-
}
|
|
280
|
+
});
|
|
123
281
|
// Only reject pending waiters once buffer is drained
|
|
124
282
|
if (this.buffer.length === 0) {
|
|
125
283
|
this.rejectAllWaiters(new Error(`WebSocket closed (code: ${code}, reason: ${reason})`));
|
|
@@ -127,11 +285,13 @@ var AsyncWS = (function (exports) {
|
|
|
127
285
|
},
|
|
128
286
|
// onError
|
|
129
287
|
(error) => {
|
|
288
|
+
// Ignore error events from a stale connection.
|
|
289
|
+
if (currentConnectionId !== this.connectionId)
|
|
290
|
+
return;
|
|
130
291
|
this.terminalError = error;
|
|
131
|
-
|
|
132
|
-
settled = true;
|
|
292
|
+
settle(() => {
|
|
133
293
|
reject(error);
|
|
134
|
-
}
|
|
294
|
+
});
|
|
135
295
|
// Reject any pending receive() waiters immediately
|
|
136
296
|
this.rejectAllWaiters(error);
|
|
137
297
|
// Don't call cleanup() here — per spec, a close event always
|
|
@@ -179,7 +339,9 @@ var AsyncWS = (function (exports) {
|
|
|
179
339
|
* Resolves when the close handshake completes.
|
|
180
340
|
*/
|
|
181
341
|
close(code, reason) {
|
|
182
|
-
if (this.state === "closed" ||
|
|
342
|
+
if (this.state === "closed" ||
|
|
343
|
+
this.state === "idle" ||
|
|
344
|
+
this.state === "errored") {
|
|
183
345
|
return Promise.resolve();
|
|
184
346
|
}
|
|
185
347
|
if (!this.socket) {
|
|
@@ -189,7 +351,9 @@ var AsyncWS = (function (exports) {
|
|
|
189
351
|
// Already closing — wait for the close event via a one-shot listener
|
|
190
352
|
return new Promise((resolve) => {
|
|
191
353
|
if (this.socket) {
|
|
192
|
-
this.socket.addEventListener("close", () => resolve(), {
|
|
354
|
+
this.socket.addEventListener("close", () => resolve(), {
|
|
355
|
+
once: true,
|
|
356
|
+
});
|
|
193
357
|
}
|
|
194
358
|
else {
|
|
195
359
|
resolve();
|
|
@@ -254,11 +418,50 @@ var AsyncWS = (function (exports) {
|
|
|
254
418
|
waiter.reject(error);
|
|
255
419
|
}
|
|
256
420
|
}
|
|
421
|
+
startKeepAlive() {
|
|
422
|
+
if (!this.keepAliveConfig || !this.socket)
|
|
423
|
+
return;
|
|
424
|
+
const { interval, timeout } = this.keepAliveConfig;
|
|
425
|
+
const pongTimeout = timeout ?? interval;
|
|
426
|
+
this.removePongListener = attachPongListener(this.socket);
|
|
427
|
+
this.keepAliveTimer = setInterval(() => {
|
|
428
|
+
if (this.state !== "open" || !this.socket)
|
|
429
|
+
return;
|
|
430
|
+
socketPing(this.socket);
|
|
431
|
+
// Clear any existing pong watchdog before starting a new one
|
|
432
|
+
// to prevent multiple timers when timeout > interval.
|
|
433
|
+
if (this.pongTimer !== null) {
|
|
434
|
+
clearTimeout(this.pongTimer);
|
|
435
|
+
}
|
|
436
|
+
this.pongTimer = setTimeout(() => {
|
|
437
|
+
if (this.state === "open" && this.socket) {
|
|
438
|
+
this.terminalError = new Error(`Keep-alive timeout: no pong received within ${pongTimeout}ms.`);
|
|
439
|
+
socketTerminate(this.socket);
|
|
440
|
+
}
|
|
441
|
+
}, pongTimeout);
|
|
442
|
+
}, interval);
|
|
443
|
+
}
|
|
444
|
+
stopKeepAlive() {
|
|
445
|
+
if (this.keepAliveTimer !== null) {
|
|
446
|
+
clearInterval(this.keepAliveTimer);
|
|
447
|
+
this.keepAliveTimer = null;
|
|
448
|
+
}
|
|
449
|
+
if (this.pongTimer !== null) {
|
|
450
|
+
clearTimeout(this.pongTimer);
|
|
451
|
+
this.pongTimer = null;
|
|
452
|
+
}
|
|
453
|
+
if (this.removePongListener) {
|
|
454
|
+
this.removePongListener();
|
|
455
|
+
this.removePongListener = null;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
257
458
|
cleanup() {
|
|
459
|
+
this.stopKeepAlive();
|
|
258
460
|
if (this.removeListeners) {
|
|
259
461
|
this.removeListeners();
|
|
260
462
|
this.removeListeners = null;
|
|
261
463
|
}
|
|
464
|
+
this.socket = null;
|
|
262
465
|
}
|
|
263
466
|
reset() {
|
|
264
467
|
this.socket = null;
|
|
@@ -267,6 +470,7 @@ var AsyncWS = (function (exports) {
|
|
|
267
470
|
this.terminalError = null;
|
|
268
471
|
this.closeInfo = null;
|
|
269
472
|
this.removeListeners = null;
|
|
473
|
+
this.stopKeepAlive();
|
|
270
474
|
}
|
|
271
475
|
}
|
|
272
476
|
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,17 @@ interface ConnectOptions {
|
|
|
4
4
|
protocols?: string | string[];
|
|
5
5
|
/** HTTP headers to send during the handshake (Node.js only). */
|
|
6
6
|
headers?: Record<string, string>;
|
|
7
|
+
/**
|
|
8
|
+
* Connection timeout in milliseconds.
|
|
9
|
+
* If the connection is not established within this time, it is aborted.
|
|
10
|
+
* Default: no timeout.
|
|
11
|
+
*/
|
|
12
|
+
timeout?: number;
|
|
13
|
+
/**
|
|
14
|
+
* An AbortSignal to cancel the connection attempt.
|
|
15
|
+
* If aborted, the connection is terminated and connect() rejects.
|
|
16
|
+
*/
|
|
17
|
+
signal?: AbortSignal;
|
|
7
18
|
}
|
|
8
19
|
/** Represents a received WebSocket message. */
|
|
9
20
|
interface WebSocketMessage {
|
|
@@ -29,6 +40,22 @@ interface ClientOptions {
|
|
|
29
40
|
* Set to 0 for unlimited. Defaults to 0 (unlimited).
|
|
30
41
|
*/
|
|
31
42
|
maxBufferSize?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Enable automatic keep-alive pings (Node.js only).
|
|
45
|
+
* In browsers, this option throws because the browser handles
|
|
46
|
+
* ping/pong at the protocol level automatically.
|
|
47
|
+
*/
|
|
48
|
+
keepAlive?: KeepAliveOptions;
|
|
49
|
+
}
|
|
50
|
+
/** Configuration for automatic keep-alive pings (Node.js only). */
|
|
51
|
+
interface KeepAliveOptions {
|
|
52
|
+
/** Interval in milliseconds between pings. Must be > 0. */
|
|
53
|
+
interval: number;
|
|
54
|
+
/**
|
|
55
|
+
* Time in milliseconds to wait for a pong response before
|
|
56
|
+
* terminating the connection. Default: same as interval.
|
|
57
|
+
*/
|
|
58
|
+
timeout?: number;
|
|
32
59
|
}
|
|
33
60
|
type WebSocketState = "idle" | "connecting" | "open" | "closing" | "closed" | "errored";
|
|
34
61
|
|
|
@@ -50,12 +77,45 @@ declare class WebSocketClient {
|
|
|
50
77
|
private terminalError;
|
|
51
78
|
private closeInfo;
|
|
52
79
|
private removeListeners;
|
|
80
|
+
private keepAliveTimer;
|
|
81
|
+
private pongTimer;
|
|
82
|
+
private removePongListener;
|
|
83
|
+
private connectionId;
|
|
53
84
|
private readonly maxBufferSize;
|
|
85
|
+
private readonly keepAliveConfig;
|
|
54
86
|
constructor(options?: ClientOptions);
|
|
87
|
+
/**
|
|
88
|
+
* Adopt an already-open WebSocket (e.g. from a `WebSocketServer` connection event).
|
|
89
|
+
*
|
|
90
|
+
* Returns a `WebSocketClient` in the "open" state, ready to send/receive.
|
|
91
|
+
* The client takes ownership of the socket lifecycle: calling `close()`
|
|
92
|
+
* will close the underlying socket.
|
|
93
|
+
*
|
|
94
|
+
* **Node.js only.** Throws in browser builds.
|
|
95
|
+
*
|
|
96
|
+
* Call this immediately in the server's `connection` handler to avoid
|
|
97
|
+
* missing messages:
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* wss.on("connection", (socket) => {
|
|
101
|
+
* const client = WebSocketClient.fromSocket(socket);
|
|
102
|
+
* const msg = await client.receive();
|
|
103
|
+
* });
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
static fromSocket(rawSocket: unknown, options?: ClientOptions): WebSocketClient;
|
|
55
107
|
/** Current connection state. */
|
|
56
108
|
get readyState(): WebSocketState;
|
|
57
109
|
/** Close info from the last close event, if any. */
|
|
58
110
|
get lastCloseInfo(): WebSocketCloseInfo | null;
|
|
111
|
+
/** The negotiated subprotocol, or empty string if none. */
|
|
112
|
+
get protocol(): string;
|
|
113
|
+
/** The URL of the WebSocket connection. */
|
|
114
|
+
get url(): string;
|
|
115
|
+
/** The number of bytes of data queued for sending. */
|
|
116
|
+
get bufferedAmount(): number;
|
|
117
|
+
/** The extensions negotiated by the server. */
|
|
118
|
+
get extensions(): string;
|
|
59
119
|
/**
|
|
60
120
|
* Connect to a WebSocket server.
|
|
61
121
|
* Resolves when the connection is open. Rejects on error.
|
|
@@ -89,9 +149,11 @@ declare class WebSocketClient {
|
|
|
89
149
|
[Symbol.asyncIterator](): AsyncGenerator<WebSocketMessage>;
|
|
90
150
|
private enqueueMessage;
|
|
91
151
|
private rejectAllWaiters;
|
|
152
|
+
private startKeepAlive;
|
|
153
|
+
private stopKeepAlive;
|
|
92
154
|
private cleanup;
|
|
93
155
|
private reset;
|
|
94
156
|
}
|
|
95
157
|
|
|
96
158
|
export { WebSocketClient };
|
|
97
|
-
export type { ClientOptions, ConnectOptions, WebSocketCloseInfo, WebSocketMessage, WebSocketState };
|
|
159
|
+
export type { ClientOptions, ConnectOptions, KeepAliveOptions, WebSocketCloseInfo, WebSocketMessage, WebSocketState };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@culpeo/async-ws",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Promise-first WebSocket client for Node.js and browsers",
|
|
5
5
|
"author": "Gerardo Lecaros",
|
|
6
6
|
"license": "MIT",
|
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
"build": "rollup -c",
|
|
59
59
|
"clean": "rimraf dist",
|
|
60
60
|
"typecheck": "tsc --noEmit",
|
|
61
|
+
"format": "prettier --write .",
|
|
62
|
+
"format:check": "prettier --check .",
|
|
61
63
|
"changeset": "changeset",
|
|
62
64
|
"version": "changeset version",
|
|
63
65
|
"release": "changeset publish",
|
|
@@ -68,17 +70,18 @@
|
|
|
68
70
|
},
|
|
69
71
|
"devDependencies": {
|
|
70
72
|
"@changesets/cli": "^2.31.0",
|
|
71
|
-
"@rollup/plugin-alias": "^
|
|
72
|
-
"@rollup/plugin-commonjs": "^
|
|
73
|
-
"@rollup/plugin-node-resolve": "^
|
|
73
|
+
"@rollup/plugin-alias": "^6.0.0",
|
|
74
|
+
"@rollup/plugin-commonjs": "^29.0.3",
|
|
75
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
74
76
|
"@rollup/plugin-typescript": "^12.1.0",
|
|
75
77
|
"@types/ws": "^8.5.12",
|
|
76
78
|
"@vitest/browser-playwright": "^4.1.8",
|
|
79
|
+
"prettier": "^3.8.3",
|
|
77
80
|
"rimraf": "^6.0.1",
|
|
78
81
|
"rollup": "^4.24.0",
|
|
79
82
|
"rollup-plugin-dts": "^6.1.1",
|
|
80
83
|
"tslib": "^2.8.0",
|
|
81
|
-
"typescript": "^
|
|
84
|
+
"typescript": "^6.0.3",
|
|
82
85
|
"vitest": "^4.1.8"
|
|
83
86
|
}
|
|
84
87
|
}
|