@laplace.live/ws 7.1.5 → 7.1.7

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/README.md CHANGED
@@ -2,12 +2,11 @@
2
2
 
3
3
  LAPLACE Live! flavored bilibili live WebSocket/TCP API.
4
4
 
5
- This project is based on [bilibili-live-ws](https://github.com/simon300000/bilibili-live-ws) and has the exact same API as the original project, with the following differences:
5
+ A modern, web-standard rewrite of [bilibili-live-ws](https://github.com/simon300000/bilibili-live-ws). It provides the same core classes (`LiveWS`, `LiveTCP`, `KeepLiveWS`, `KeepLiveTCP`) but uses a different event API and drops all Node.js polyfills:
6
6
 
7
7
  - Pure ESM
8
- - Uses web-standard `EventTarget`/`Event` instead of Node.js `EventEmitter` polyfills
9
- - Uses native `WebSocket` API directly, removing `isomorphic-ws` and `ws` dependencies
10
- - No `Buffer` polyfills
8
+ - Web-standard `EventTarget`/`Event` instead of Node.js `EventEmitter` — use `addEventListener` / `removeEventListener` instead of `.on()` / `.once()`
9
+ - Native `WebSocket` API directly no `isomorphic-ws` or `ws` dependencies
11
10
  - Typed `addEventListener` via `LiveEventMap` with `@laplace.live/internal` types
12
11
  - Conditional `exports` field with `./server`, `./client`, `./browser` sub-path exports
13
12
 
@@ -73,6 +72,45 @@ const live = new LiveTCP(25034104, { key: "..." });
73
72
  live.addEventListener("heartbeat", ({ data }) => console.log("Online:", data));
74
73
  ```
75
74
 
75
+ ## Migrating from bilibili-live-ws
76
+
77
+ ### Event listeners
78
+
79
+ Replace `.on()` / `.once()` with `addEventListener()` / `removeEventListener()`.
80
+ Event data is accessed via the event object's `.data` property instead of direct
81
+ callback arguments:
82
+
83
+ ```diff
84
+ - live.on('heartbeat', (online) => console.log(online));
85
+ + live.addEventListener('heartbeat', ({ data: online }) => console.log(online));
86
+
87
+ - live.on('DANMU_MSG', (data) => console.log(data));
88
+ + live.addEventListener('DANMU_MSG', ({ data }) => console.log(data));
89
+
90
+ - live.once('live', () => console.log('entered'));
91
+ + live.addEventListener('live', () => console.log('entered'), { once: true });
92
+ ```
93
+
94
+ ### Catch-all event
95
+
96
+ The `relayEvent` symbol is replaced by an `event` meta-event:
97
+
98
+ ```diff
99
+ - const { relayEvent } = require('bilibili-live-ws');
100
+ - live.on(relayEvent, (name, data) => ...);
101
+ + live.addEventListener('event', ({ data }) => ...);
102
+ ```
103
+
104
+ ### Buffer → Uint8Array
105
+
106
+ Raw data uses `Uint8Array` instead of `Buffer`. If you pass a custom
107
+ `authBody` as binary, use `Uint8Array`:
108
+
109
+ ```diff
110
+ - live = new LiveWS(roomid, { authBody: Buffer.from(...) });
111
+ + live = new LiveWS(roomid, { authBody: new Uint8Array(...) });
112
+ ```
113
+
76
114
  ## License
77
115
 
78
116
  MIT
package/dist/browser.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { K as KeepLive, b as LiveWSBase, W as WSOptions } from './ws-CAEZj7O-.js';
2
- export { c as LaplaceRawEvent, d as LiveEventMap, a as LiveOptions } from './ws-CAEZj7O-.js';
1
+ import { K as KeepLive, b as LiveWSBase, W as WSOptions } from './ws-mjTot1Nb.js';
2
+ export { c as LaplaceEventTarget, d as LaplaceRawEvent, e as LiveEventMap, a as LiveOptions } from './ws-mjTot1Nb.js';
3
3
  import '@laplace.live/internal';
4
4
 
5
5
  /**
package/dist/browser.js CHANGED
@@ -1798,9 +1798,16 @@ var LaplaceRawEvent = class extends Event {
1798
1798
  this.data = data;
1799
1799
  }
1800
1800
  };
1801
+ var LaplaceEventTarget = class extends EventTarget {
1802
+ dispatchEvent(event) {
1803
+ const result = super.dispatchEvent(event);
1804
+ super.dispatchEvent(new LaplaceRawEvent("event", event));
1805
+ return result;
1806
+ }
1807
+ };
1801
1808
 
1802
1809
  // src/keep-live.ts
1803
- var KeepLive = class extends EventTarget {
1810
+ var KeepLive = class extends LaplaceEventTarget {
1804
1811
  /** @internal Factory that creates a fresh connection with the original arguments. */
1805
1812
  createConnection;
1806
1813
  /** `true` after {@link close} has been called; prevents further reconnects. */
@@ -1820,15 +1827,6 @@ var KeepLive = class extends EventTarget {
1820
1827
  this.connection = this.createConnection();
1821
1828
  this.connect(false);
1822
1829
  }
1823
- /**
1824
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
1825
- * for every event, enabling catch-all listeners.
1826
- */
1827
- dispatchEvent(event) {
1828
- const result = super.dispatchEvent(event);
1829
- super.dispatchEvent(new LaplaceRawEvent("event", event));
1830
- return result;
1831
- }
1832
1830
  /**
1833
1831
  * Wire up event forwarding and timeout handling on the current connection.
1834
1832
  * When `reconnect` is `true`, the previous connection is closed and a fresh
@@ -1992,7 +1990,7 @@ var encoder = (type, body = "") => {
1992
1990
  };
1993
1991
 
1994
1992
  // src/live.ts
1995
- var Live = class extends EventTarget {
1993
+ var Live = class extends LaplaceEventTarget {
1996
1994
  /** The live room ID this instance is connected to. */
1997
1995
  roomid;
1998
1996
  /** Latest known online viewer count, updated on each heartbeat. */
@@ -2083,15 +2081,6 @@ var Live = class extends EventTarget {
2083
2081
  this.dispatchEvent(new Event("error"));
2084
2082
  });
2085
2083
  }
2086
- /**
2087
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
2088
- * for every event, enabling catch-all listeners.
2089
- */
2090
- dispatchEvent(event) {
2091
- const result = super.dispatchEvent(event);
2092
- super.dispatchEvent(new LaplaceRawEvent("event", event));
2093
- return result;
2094
- }
2095
2084
  /** Send a heartbeat packet to the server. */
2096
2085
  heartbeat() {
2097
2086
  this.send(encoder("heartbeat"));
@@ -2111,8 +2100,8 @@ var Live = class extends EventTarget {
2111
2100
  var LiveWSBase = class extends Live {
2112
2101
  /** The underlying native WebSocket instance. */
2113
2102
  ws;
2114
- constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", ...options } = {}) {
2115
- const ws = new WebSocket(address);
2103
+ constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", createWebSocket, ...options } = {}) {
2104
+ const ws = createWebSocket ? createWebSocket(address) : new WebSocket(address);
2116
2105
  const send = (data) => {
2117
2106
  if (ws.readyState === 1) {
2118
2107
  ws.send(data);
@@ -2142,6 +2131,7 @@ var KeepLiveWS = class extends KeepLive {
2142
2131
  };
2143
2132
  export {
2144
2133
  KeepLiveWS,
2134
+ LaplaceEventTarget,
2145
2135
  LaplaceRawEvent,
2146
2136
  LiveWS
2147
2137
  };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive, b as LiveWSBase, W as WSOptions } from './ws-CAEZj7O-.js';
2
- export { c as LaplaceRawEvent, d as LiveEventMap } from './ws-CAEZj7O-.js';
1
+ import { L as Live, I as Inflates, a as LiveOptions, K as KeepLive, b as LiveWSBase, W as WSOptions } from './ws-mjTot1Nb.js';
2
+ export { c as LaplaceEventTarget, d as LaplaceRawEvent, e as LiveEventMap } from './ws-mjTot1Nb.js';
3
3
  import { Socket } from 'node:net';
4
4
  import { BilibiliInternal } from '@laplace.live/internal';
5
5
 
package/dist/index.js CHANGED
@@ -15,9 +15,16 @@ var LaplaceRawEvent = class extends Event {
15
15
  this.data = data;
16
16
  }
17
17
  };
18
+ var LaplaceEventTarget = class extends EventTarget {
19
+ dispatchEvent(event) {
20
+ const result = super.dispatchEvent(event);
21
+ super.dispatchEvent(new LaplaceRawEvent("event", event));
22
+ return result;
23
+ }
24
+ };
18
25
 
19
26
  // src/keep-live.ts
20
- var KeepLive = class extends EventTarget {
27
+ var KeepLive = class extends LaplaceEventTarget {
21
28
  /** @internal Factory that creates a fresh connection with the original arguments. */
22
29
  createConnection;
23
30
  /** `true` after {@link close} has been called; prevents further reconnects. */
@@ -37,15 +44,6 @@ var KeepLive = class extends EventTarget {
37
44
  this.connection = this.createConnection();
38
45
  this.connect(false);
39
46
  }
40
- /**
41
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
42
- * for every event, enabling catch-all listeners.
43
- */
44
- dispatchEvent(event) {
45
- const result = super.dispatchEvent(event);
46
- super.dispatchEvent(new LaplaceRawEvent("event", event));
47
- return result;
48
- }
49
47
  /**
50
48
  * Wire up event forwarding and timeout handling on the current connection.
51
49
  * When `reconnect` is `true`, the previous connection is closed and a fresh
@@ -212,7 +210,7 @@ var encoder = (type, body = "") => {
212
210
  };
213
211
 
214
212
  // src/live.ts
215
- var Live = class extends EventTarget {
213
+ var Live = class extends LaplaceEventTarget {
216
214
  /** The live room ID this instance is connected to. */
217
215
  roomid;
218
216
  /** Latest known online viewer count, updated on each heartbeat. */
@@ -303,15 +301,6 @@ var Live = class extends EventTarget {
303
301
  this.dispatchEvent(new Event("error"));
304
302
  });
305
303
  }
306
- /**
307
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
308
- * for every event, enabling catch-all listeners.
309
- */
310
- dispatchEvent(event) {
311
- const result = super.dispatchEvent(event);
312
- super.dispatchEvent(new LaplaceRawEvent("event", event));
313
- return result;
314
- }
315
304
  /** Send a heartbeat packet to the server. */
316
305
  heartbeat() {
317
306
  this.send(encoder("heartbeat"));
@@ -378,8 +367,8 @@ var LiveTCPBase = class extends Live {
378
367
  var LiveWSBase = class extends Live {
379
368
  /** The underlying native WebSocket instance. */
380
369
  ws;
381
- constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", ...options } = {}) {
382
- const ws = new WebSocket(address);
370
+ constructor(inflates2, roomid, { address = "wss://broadcastlv.chat.bilibili.com/sub", createWebSocket, ...options } = {}) {
371
+ const ws = createWebSocket ? createWebSocket(address) : new WebSocket(address);
383
372
  const send = (data) => {
384
373
  if (ws.readyState === 1) {
385
374
  ws.send(data);
@@ -443,6 +432,7 @@ var KeepLiveTCP = class extends KeepLive {
443
432
  export {
444
433
  KeepLiveTCP,
445
434
  KeepLiveWS,
435
+ LaplaceEventTarget,
446
436
  LaplaceRawEvent,
447
437
  LiveTCP,
448
438
  LiveWS,
@@ -101,6 +101,37 @@ interface LiveEventMap {
101
101
  LIVE_OPEN_PLATFORM_LIVE_END: LaplaceRawEvent<BilibiliInternal.WebSocket.OpenPlatform.LIVE_OPEN_PLATFORM_LIVE_END>;
102
102
  LIVE_OPEN_PLATFORM_INTERACTION_END: LaplaceRawEvent<BilibiliInternal.WebSocket.OpenPlatform.LIVE_OPEN_PLATFORM_INTERACTION_END>;
103
103
  }
104
+ /**
105
+ * Typed {@link EventTarget} base class for live connections.
106
+ *
107
+ * Provides typed `addEventListener` / `removeEventListener` via
108
+ * {@link LiveEventMap} and a `dispatchEvent` override that emits a
109
+ * catch-all `"event"` meta-event for every dispatched event.
110
+ *
111
+ * Extend this instead of `EventTarget` when building wrappers around
112
+ * `LiveWS` / `KeepLiveWS` to inherit typed event signatures
113
+ * automatically — no `declare` duplication required.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * import { LaplaceEventTarget, LaplaceRawEvent } from '@laplace.live/ws'
118
+ *
119
+ * class MyWrapper extends LaplaceEventTarget {
120
+ * // addEventListener is already typed — no extra `declare` needed
121
+ * }
122
+ * ```
123
+ */
124
+ declare class LaplaceEventTarget extends EventTarget {
125
+ dispatchEvent(event: Event): boolean;
126
+ addEventListener: {
127
+ <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
128
+ <T = unknown>(type: string, listener: (ev: LaplaceRawEvent<T>) => void, options?: boolean | AddEventListenerOptions): void;
129
+ };
130
+ removeEventListener: {
131
+ <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | EventListenerOptions): void;
132
+ (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
133
+ };
134
+ }
104
135
 
105
136
  /**
106
137
  * Options for configuring the Bilibili live connection authentication.
@@ -127,7 +158,7 @@ type LiveOptions = {
127
158
  /**
128
159
  * Base class for a single Bilibili live room connection.
129
160
  *
130
- * Extends {@link EventTarget} and emits the following events:
161
+ * Extends {@link LaplaceEventTarget} and emits the following events:
131
162
  *
132
163
  * | Event | Payload | Description |
133
164
  * |---------------|--------------------|--------------------------------------------------|
@@ -149,7 +180,7 @@ type LiveOptions = {
149
180
  *
150
181
  * @throws {Error} If `roomid` is not a finite number.
151
182
  */
152
- declare class Live extends EventTarget {
183
+ declare class Live extends LaplaceEventTarget {
153
184
  /** The live room ID this instance is connected to. */
154
185
  roomid: number;
155
186
  /** Latest known online viewer count, updated on each heartbeat. */
@@ -168,11 +199,6 @@ declare class Live extends EventTarget {
168
199
  send: (data: Uint8Array) => void;
169
200
  close: () => void;
170
201
  } & LiveOptions);
171
- /**
172
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
173
- * for every event, enabling catch-all listeners.
174
- */
175
- dispatchEvent(event: Event): boolean;
176
202
  /** Send a heartbeat packet to the server. */
177
203
  heartbeat(): void;
178
204
  /**
@@ -181,36 +207,6 @@ declare class Live extends EventTarget {
181
207
  * @returns A promise that resolves with the current online count.
182
208
  */
183
209
  getOnline(): Promise<number>;
184
- /**
185
- * Typed `addEventListener` that narrows the inherited {@link EventTarget}
186
- * signature using {@link LiveEventMap}.
187
- *
188
- * - Known events (e.g. `"heartbeat"`, `"DANMU_MSG"`) are auto-typed.
189
- * - Unknown/dynamic events accept a generic `<T>` for the payload type.
190
- *
191
- * Uses `declare` to shadow the inherited type without emitting code —
192
- * at runtime this is still `EventTarget.prototype.addEventListener`.
193
- *
194
- * @example
195
- * ```ts
196
- * live.addEventListener('heartbeat', (e) => console.log(e.data))
197
- * live.addEventListener('DANMU_MSG', ({ data }) => console.log(data.msg_id))
198
- * live.addEventListener<CustomType>('NEW_CMD', ({ data }) => console.log(data))
199
- * ```
200
- */
201
- addEventListener: {
202
- <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
203
- <T = unknown>(type: string, listener: (ev: LaplaceRawEvent<T>) => void, options?: boolean | AddEventListenerOptions): void;
204
- };
205
- /**
206
- * Typed `removeEventListener` matching {@link addEventListener}.
207
- *
208
- * Uses `declare` to shadow the inherited type without emitting code.
209
- */
210
- removeEventListener: {
211
- <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | EventListenerOptions): void;
212
- (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
213
- };
214
210
  }
215
211
 
216
212
  /**
@@ -230,7 +226,7 @@ declare class Live extends EventTarget {
230
226
  * keep.addEventListener('DANMU_MSG', ({ data }) => console.log('danmaku:', data.msg_id))
231
227
  * ```
232
228
  */
233
- declare class KeepLive<T extends Live> extends EventTarget {
229
+ declare class KeepLive<T extends Live> extends LaplaceEventTarget {
234
230
  /** @internal Factory that creates a fresh connection with the original arguments. */
235
231
  private createConnection;
236
232
  /** `true` after {@link close} has been called; prevents further reconnects. */
@@ -242,11 +238,6 @@ declare class KeepLive<T extends Live> extends EventTarget {
242
238
  /** The current underlying connection instance. */
243
239
  connection: T;
244
240
  constructor(createConnection: () => T);
245
- /**
246
- * Overridden to also dispatch a `LaplaceRawEvent<Event>` with type `"event"`
247
- * for every event, enabling catch-all listeners.
248
- */
249
- dispatchEvent(event: Event): boolean;
250
241
  /**
251
242
  * Wire up event forwarding and timeout handling on the current connection.
252
243
  * When `reconnect` is `true`, the previous connection is closed and a fresh
@@ -274,16 +265,6 @@ declare class KeepLive<T extends Live> extends EventTarget {
274
265
  * @param data - The binary packet to send.
275
266
  */
276
267
  send(data: Uint8Array): void;
277
- /** {@inheritDoc Live.addEventListener} */
278
- addEventListener: {
279
- <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
280
- <T = unknown>(type: string, listener: (ev: LaplaceRawEvent<T>) => void, options?: boolean | AddEventListenerOptions): void;
281
- };
282
- /** {@inheritDoc Live.removeEventListener} */
283
- removeEventListener: {
284
- <K extends keyof LiveEventMap>(type: K, listener: (ev: LiveEventMap[K]) => void, options?: boolean | EventListenerOptions): void;
285
- (type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
286
- };
287
268
  }
288
269
 
289
270
  /**
@@ -293,6 +274,8 @@ declare class KeepLive<T extends Live> extends EventTarget {
293
274
  type WSOptions = LiveOptions & {
294
275
  /** WebSocket server URL. Defaults to `wss://broadcastlv.chat.bilibili.com/sub`. */
295
276
  address?: string;
277
+ /** Factory to create the WebSocket (e.g. for runtime-specific options like Bun's proxy). */
278
+ createWebSocket?: (address: string) => WebSocket;
296
279
  };
297
280
  /**
298
281
  * WebSocket transport for Bilibili live room connections.
@@ -312,7 +295,7 @@ type WSOptions = LiveOptions & {
312
295
  declare class LiveWSBase extends Live {
313
296
  /** The underlying native WebSocket instance. */
314
297
  ws: WebSocket;
315
- constructor(inflates: Inflates, roomid: number, { address, ...options }?: WSOptions);
298
+ constructor(inflates: Inflates, roomid: number, { address, createWebSocket, ...options }?: WSOptions);
316
299
  }
317
300
 
318
- export { type Inflates as I, KeepLive as K, Live as L, type WSOptions as W, type LiveOptions as a, LiveWSBase as b, LaplaceRawEvent as c, type LiveEventMap as d };
301
+ export { type Inflates as I, KeepLive as K, Live as L, type WSOptions as W, type LiveOptions as a, LiveWSBase as b, LaplaceEventTarget as c, LaplaceRawEvent as d, type LiveEventMap as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@laplace.live/ws",
3
- "version": "7.1.5",
3
+ "version": "7.1.7",
4
4
  "description": "LAPLACE Live! flavored bilibili live WebSocket/TCP API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",