@laplace.live/event-bridge-sdk 1.0.7 → 1.0.22

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
@@ -103,9 +103,9 @@ enum ConnectionState {
103
103
 
104
104
  - `connect()`: Connect to the event bridge. Returns a Promise that resolves when connected.
105
105
  - `disconnect()`: Disconnect from the event bridge.
106
- - `on(eventType, handler)`: Register an event handler for a specific event type with automatic type inference.
107
- - `onAny(handler)`: Register a handler for all events.
108
- - `onConnectionStateChange(handler)`: Register a handler for connection state changes.
106
+ - `on(eventType, handler)`: Register an event handler for a specific event type with automatic type inference. Returns an unsubscribe function.
107
+ - `onAny(handler)`: Register a handler for all events. Returns an unsubscribe function.
108
+ - `onConnectionStateChange(handler)`: Register a handler for connection state changes. Returns an unsubscribe function.
109
109
  - `off(eventType, handler)`: Remove an event handler for a specific event type.
110
110
  - `offAny(handler)`: Remove a handler for all events.
111
111
  - `offConnectionStateChange(handler)`: Remove a connection state change handler.
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var K;((A)=>{A.DISCONNECTED="disconnected";A.CONNECTING="connecting";A.CONNECTED="connected";A.RECONNECTING="reconnecting"})(K||={});class N{ws=null;eventHandlers=new Map;anyEventHandlers=[];connectionStateHandlers=[];reconnectTimer=null;reconnectAttempts=0;clientId=null;serverVersion=null;connectionState="disconnected";lastPingTime=null;pingMonitorTimer=null;options={url:"ws://localhost:9696",token:"",reconnect:!0,reconnectInterval:3000,maxReconnectAttempts:1000,pingTimeout:90000};constructor(q={}){this.options={...this.options,...q}}connect(){return new Promise((q,z)=>{try{if(this.ws)this.ws.close();this.setConnectionState("connecting");let w=this.options.url,B=[];if(this.options.token){B.push("laplace-event-bridge-role-client",this.options.token);let A=new URL(w);A.searchParams.set("token",this.options.token),w=A.toString()}this.ws=new WebSocket(w,B),this.ws.onopen=()=>{this.setConnectionState("connected"),this.reconnectAttempts=0,q()},this.ws.onmessage=(A)=>{try{let E=JSON.parse(A.data);if(E.type==="ping"){this.lastPingTime=Date.now(),this.ws?.send(JSON.stringify({type:"pong",timestamp:Date.now(),respondingTo:E.timestamp}));return}if(E.type==="established"){this.clientId=E.clientId,this.serverVersion=E.version;let G=(()=>{let F=new URL(w);if(F.searchParams.has("token"))F.searchParams.set("token","***");return F.toString()})();if(console.log(`Welcome to LAPLACE Event Bridge ${`v${E.version}`||"(unknown version)"}: ${G} with client ID ${this.clientId||"unknown"}`),this.shouldMonitorPing())this.startPingMonitoring()}this.processEvent(E)}catch(E){console.error("Failed to parse event data:",E)}},this.ws.onerror=(A)=>{console.error("WebSocket error:",A),z(A)},this.ws.onclose=()=>{if(console.log("Disconnected from LAPLACE Event Bridge"),this.stopPingMonitoring(),this.lastPingTime=null,this.options.reconnect&&this.reconnectAttempts<this.options.maxReconnectAttempts){this.reconnectAttempts++,this.setConnectionState("reconnecting");let A=this.options.reconnectInterval,E=1.5,G=60000,F=Math.min(A*E**(this.reconnectAttempts-1),G),H=Math.round(F);console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts}) in ${H}ms...`),this.reconnectTimer=setTimeout(()=>{this.connect().catch((J)=>{console.error("Reconnection failed:",J)})},H)}else this.setConnectionState("disconnected")}}catch(w){this.setConnectionState("disconnected"),z(w)}})}disconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.stopPingMonitoring(),this.ws)this.ws.close(),this.ws=null;this.setConnectionState("disconnected"),this.clientId=null,this.serverVersion=null,this.lastPingTime=null}on(q,z){let w=this.eventHandlers.get(q)||[];w.push(z),this.eventHandlers.set(q,w)}onAny(q){this.anyEventHandlers.push(q)}onConnectionStateChange(q){this.connectionStateHandlers.push(q),q(this.connectionState)}off(q,z){let w=this.eventHandlers.get(q);if(!w)return;let B=w.indexOf(z);if(B!==-1)w.splice(B,1);if(w.length===0)this.eventHandlers.delete(q)}offAny(q){let z=this.anyEventHandlers.indexOf(q);if(z!==-1)this.anyEventHandlers.splice(z,1)}offConnectionStateChange(q){let z=this.connectionStateHandlers.indexOf(q);if(z!==-1)this.connectionStateHandlers.splice(z,1)}isConnectedToBridge(){return this.connectionState==="connected"}getConnectionState(){return this.connectionState}getClientId(){return this.clientId}send(q){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw Error("Not connected to LAPLACE Event Bridge");this.ws.send(JSON.stringify(q))}setConnectionState(q){if(this.connectionState!==q){this.connectionState=q;for(let z of this.connectionStateHandlers)try{z(q)}catch(w){console.error("Error in connection state change handler:",w)}}}processEvent(q){let z=this.eventHandlers.get(q.type);if(z)for(let w of z)try{w(q)}catch(B){console.error(`Error in event handler for type ${q.type}:`,B)}for(let w of this.anyEventHandlers)try{w(q)}catch(B){console.error("Error in any event handler:",B)}}shouldMonitorPing(){if(!this.serverVersion)return!1;let q=this.serverVersion.split(".").map((A)=>parseInt(A,10));if(q.length<3||q.some(Number.isNaN))return console.warn(`Invalid server version format: ${this.serverVersion}`),!1;let[z=0,w=0,B=0]=q;if(z>4)return!0;if(z===4){if(w>0)return!0;if(w===0&&B>=3)return!0}return!1}startPingMonitoring(){this.stopPingMonitoring(),console.log(`Ping monitoring enabled (timeout: ${this.options.pingTimeout}ms)`),this.lastPingTime=Date.now(),this.pingMonitorTimer=setInterval(()=>{if(!this.lastPingTime)return;let q=Date.now()-this.lastPingTime;if(q>this.options.pingTimeout){if(console.warn(`Ping timeout detected (${q}ms since last ping). Reconnecting...`),this.stopPingMonitoring(),this.ws)this.ws.close()}},this.options.pingTimeout/3)}stopPingMonitoring(){if(this.pingMonitorTimer)clearInterval(this.pingMonitorTimer),this.pingMonitorTimer=null}}export{N as LaplaceEventBridgeClient,K as ConnectionState};
1
+ var K;((A)=>{A.DISCONNECTED="disconnected";A.CONNECTING="connecting";A.CONNECTED="connected";A.RECONNECTING="reconnecting"})(K||={});class N{ws=null;eventHandlers=new Map;anyEventHandlers=[];connectionStateHandlers=[];reconnectTimer=null;reconnectAttempts=0;clientId=null;serverVersion=null;connectionState="disconnected";lastPingTime=null;pingMonitorTimer=null;options={url:"ws://localhost:9696",token:"",reconnect:!0,reconnectInterval:3000,maxReconnectAttempts:1000,pingTimeout:90000};constructor(q={}){this.options={...this.options,...q}}connect(){return new Promise((q,z)=>{try{if(this.ws)this.ws.close();this.setConnectionState("connecting");let w=this.options.url,E=[];if(this.options.token){E.push("laplace-event-bridge-role-client",this.options.token);let A=new URL(w);A.searchParams.set("token",this.options.token),w=A.toString()}this.ws=new WebSocket(w,E),this.ws.onopen=()=>{this.setConnectionState("connected"),this.reconnectAttempts=0,q()},this.ws.onmessage=(A)=>{try{let B=JSON.parse(A.data);if(B.type==="ping"){this.lastPingTime=Date.now(),this.ws?.send(JSON.stringify({type:"pong",timestamp:Date.now(),respondingTo:B.timestamp}));return}if(B.type==="established"){this.clientId=B.clientId,this.serverVersion=B.version;let G=(()=>{let F=new URL(w);if(F.searchParams.has("token"))F.searchParams.set("token","***");return F.toString()})();if(console.log(`Welcome to LAPLACE Event Bridge ${B.version?`v${B.version}`:"(unknown version)"}: ${G} with client ID ${this.clientId||"unknown"}`),this.shouldMonitorPing())this.startPingMonitoring()}this.processEvent(B)}catch(B){console.error("Failed to parse event data:",B)}},this.ws.onerror=(A)=>{console.error("WebSocket error:",A),z(A)},this.ws.onclose=()=>{if(console.log("Disconnected from LAPLACE Event Bridge"),this.stopPingMonitoring(),this.lastPingTime=null,this.options.reconnect&&this.reconnectAttempts<this.options.maxReconnectAttempts){this.reconnectAttempts++,this.setConnectionState("reconnecting");let A=this.options.reconnectInterval,B=1.5,G=60000,F=Math.min(A*B**(this.reconnectAttempts-1),G),H=Math.round(F);console.log(`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts}) in ${H}ms...`),this.reconnectTimer=setTimeout(()=>{this.connect().catch((J)=>{console.error("Reconnection failed:",J)})},H)}else this.setConnectionState("disconnected")}}catch(w){this.setConnectionState("disconnected"),z(w)}})}disconnect(){if(this.reconnectTimer)clearTimeout(this.reconnectTimer),this.reconnectTimer=null;if(this.stopPingMonitoring(),this.ws)this.ws.close(),this.ws=null;this.setConnectionState("disconnected"),this.clientId=null,this.serverVersion=null,this.lastPingTime=null}on(q,z){let w=this.eventHandlers.get(q)||[];return w.push(z),this.eventHandlers.set(q,w),()=>this.off(q,z)}onAny(q){return this.anyEventHandlers.push(q),()=>this.offAny(q)}onConnectionStateChange(q){return this.connectionStateHandlers.push(q),q(this.connectionState),()=>this.offConnectionStateChange(q)}off(q,z){let w=this.eventHandlers.get(q);if(!w)return;let E=w.indexOf(z);if(E!==-1)w.splice(E,1);if(w.length===0)this.eventHandlers.delete(q)}offAny(q){let z=this.anyEventHandlers.indexOf(q);if(z!==-1)this.anyEventHandlers.splice(z,1)}offConnectionStateChange(q){let z=this.connectionStateHandlers.indexOf(q);if(z!==-1)this.connectionStateHandlers.splice(z,1)}isConnectedToBridge(){return this.connectionState==="connected"}getConnectionState(){return this.connectionState}getClientId(){return this.clientId}send(q){if(!this.ws||this.ws.readyState!==WebSocket.OPEN)throw Error("Not connected to LAPLACE Event Bridge");this.ws.send(JSON.stringify(q))}setConnectionState(q){if(this.connectionState!==q){this.connectionState=q;for(let z of this.connectionStateHandlers)try{z(q)}catch(w){console.error("Error in connection state change handler:",w)}}}processEvent(q){let z=this.eventHandlers.get(q.type);if(z)for(let w of z)try{w(q)}catch(E){console.error(`Error in event handler for type ${q.type}:`,E)}for(let w of this.anyEventHandlers)try{w(q)}catch(E){console.error("Error in any event handler:",E)}}shouldMonitorPing(){if(!this.serverVersion)return!1;let q=this.serverVersion.split(".").map((A)=>parseInt(A,10));if(q.length<3||q.some(Number.isNaN))return console.warn(`Invalid server version format: ${this.serverVersion}`),!1;let[z=0,w=0,E=0]=q;if(z>4)return!0;if(z===4){if(w>0)return!0;if(w===0&&E>=3)return!0}return!1}startPingMonitoring(){this.stopPingMonitoring(),console.log(`Ping monitoring enabled (timeout: ${this.options.pingTimeout}ms)`),this.lastPingTime=Date.now(),this.pingMonitorTimer=setInterval(()=>{if(!this.lastPingTime)return;let q=Date.now()-this.lastPingTime;if(q>this.options.pingTimeout){if(console.warn(`Ping timeout detected (${q}ms since last ping). Reconnecting...`),this.stopPingMonitoring(),this.ws)this.ws.close()}},this.options.pingTimeout/3)}stopPingMonitoring(){if(this.pingMonitorTimer)clearInterval(this.pingMonitorTimer),this.pingMonitorTimer=null}}export{N as LaplaceEventBridgeClient,K as ConnectionState};
package/index.ts CHANGED
@@ -14,7 +14,6 @@ export type EventTypeMap = {
14
14
  }
15
15
 
16
16
  export type EventHandler<T extends LaplaceEvent> = (event: T) => void
17
- export type EventTypeHandler = (event: LaplaceEvent) => void
18
17
  export type AnyEventHandler = (event: LaplaceEvent) => void
19
18
  export type ConnectionStateChangeHandler = (state: ConnectionState) => void
20
19
 
@@ -158,7 +157,7 @@ export class LaplaceEventBridgeClient {
158
157
  })()
159
158
 
160
159
  console.log(
161
- `Welcome to LAPLACE Event Bridge ${`v${data.version}` || '(unknown version)'}: ${displayUrl} with client ID ${this.clientId || 'unknown'}`
160
+ `Welcome to LAPLACE Event Bridge ${data.version ? `v${data.version}` : '(unknown version)'}: ${displayUrl} with client ID ${this.clientId || 'unknown'}`
162
161
  )
163
162
 
164
163
  // Start ping monitoring if server version supports it (>= 4.0.2)
@@ -249,29 +248,35 @@ export class LaplaceEventBridgeClient {
249
248
  * Register an event handler for a specific event type
250
249
  * @param eventType The event type to listen for
251
250
  * @param handler The handler function to call when the event is received
251
+ * @returns A function that removes the handler when called
252
252
  */
253
- public on<T extends LaplaceEventTypes>(eventType: T, handler: (event: EventTypeMap[T]) => void): void {
253
+ public on<T extends LaplaceEventTypes>(eventType: T, handler: (event: EventTypeMap[T]) => void): () => void {
254
254
  const handlers = this.eventHandlers.get(eventType) || []
255
255
  handlers.push(handler)
256
256
  this.eventHandlers.set(eventType, handlers)
257
+ return () => this.off(eventType, handler)
257
258
  }
258
259
 
259
260
  /**
260
261
  * Register a handler for all events
261
262
  * @param handler The handler function to call for any event
263
+ * @returns A function that removes the handler when called
262
264
  */
263
- public onAny(handler: AnyEventHandler): void {
265
+ public onAny(handler: AnyEventHandler): () => void {
264
266
  this.anyEventHandlers.push(handler)
267
+ return () => this.offAny(handler)
265
268
  }
266
269
 
267
270
  /**
268
271
  * Register a handler for connection state changes
269
272
  * @param handler The handler function to call when the connection state changes
273
+ * @returns A function that removes the handler when called
270
274
  */
271
- public onConnectionStateChange(handler: ConnectionStateChangeHandler): void {
275
+ public onConnectionStateChange(handler: ConnectionStateChangeHandler): () => void {
272
276
  this.connectionStateHandlers.push(handler)
273
277
  // Immediately call with current state to initialize
274
278
  handler(this.connectionState)
279
+ return () => this.offConnectionStateChange(handler)
275
280
  }
276
281
 
277
282
  /**
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@laplace.live/event-bridge-sdk",
3
3
  "description": "LAPLACE Event Bridge SDK",
4
- "version": "1.0.7",
4
+ "version": "1.0.22",
5
5
  "module": "index.ts",
6
6
  "types": "index.ts",
7
7
  "license": "MIT",
8
8
  "type": "module",
9
- "repository": "laplace-live/event-bridge",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/laplace-live/event-bridge.git",
12
+ "directory": "packages/sdk"
13
+ },
10
14
  "homepage": "https://chat.laplace.live",
11
15
  "scripts": {
12
16
  "build": "bun build index.ts --outdir dist --target browser --minify",
@@ -25,8 +29,12 @@
25
29
  "README.md",
26
30
  "LICENSE"
27
31
  ],
32
+ "publishConfig": {
33
+ "access": "public",
34
+ "provenance": true
35
+ },
28
36
  "dependencies": {
29
- "@laplace.live/event-types": "^2.0.13"
37
+ "@laplace.live/event-types": "^2.0.14"
30
38
  },
31
39
  "devDependencies": {
32
40
  "bun-types": "latest"