@laplace.live/event-bridge-server 0.2.0 → 0.2.2

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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # @laplace.live/event-bridge-server
2
2
 
3
+ ## 0.2.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 2ef27cf: release artifacts test
8
+
9
+ ## 0.2.1
10
+
11
+ ### Patch Changes
12
+
13
+ - 818636b: enhance configuration options for authentication and debug mode
14
+ - 6fbc787: add network interface configuration options
15
+
3
16
  ## 0.2.0
4
17
 
5
18
  ### Minor Changes
package/README.md CHANGED
@@ -54,6 +54,23 @@ bun run start --auth "your-secure-token"
54
54
 
55
55
  If the authentication token is set, all connections including the clients must provide it to connect.
56
56
 
57
+ ### Network Interface
58
+
59
+ Control which network interface the server listens on:
60
+
61
+ 1. Environment variable: `HOST="127.0.0.1"`
62
+ 2. Command line: `--host 127.0.0.1`
63
+
64
+ ```bash
65
+ # Listen only on localhost
66
+ export HOST="localhost"
67
+
68
+ # Listen on all interfaces
69
+ bun run start --host 0.0.0.0
70
+ ```
71
+
72
+ By default, the server listens on `localhost`.
73
+
57
74
  ### Debug Mode
58
75
 
59
76
  Enable detailed debug logging using:
@@ -78,13 +95,13 @@ bun run start --debug
78
95
  bun run start
79
96
 
80
97
  # Start with CLI options
81
- bun run start --debug --auth "your-secure-token"
98
+ bun run start --debug --auth "your-secure-token" --host 0.0.0.0
82
99
 
83
100
  # Or with hot reloading during development
84
101
  bun run dev
85
102
  ```
86
103
 
87
- The WebSocket bridge server runs on `http://localhost:9696`.
104
+ The WebSocket bridge server runs on `http://localhost:9696` by default.
88
105
 
89
106
  ### Connection Types
90
107
 
package/index.ts ADDED
@@ -0,0 +1,191 @@
1
+ import { parseArgs } from 'util'
2
+ import type { LaplaceEvent } from '@laplace.live/event-types'
3
+
4
+ // Parse command line arguments properly
5
+ const { values } = parseArgs({
6
+ args: Bun.argv,
7
+ options: {
8
+ debug: {
9
+ type: 'boolean',
10
+ },
11
+ auth: {
12
+ type: 'string',
13
+ },
14
+ host: {
15
+ type: 'string',
16
+ },
17
+ },
18
+ strict: false,
19
+ })
20
+
21
+ // Get authentication token from environment variable or CLI
22
+ const AUTH_TOKEN = process.env['LEB_AUTH'] || process.env['LAPLACE_EVENT_BRIDGE_AUTH'] || values.auth || ''
23
+
24
+ // Debug mode configuration
25
+ const DEBUG_MODE = process.env['DEBUG'] === '1' || process.env['DEBUG']?.toLowerCase() === 'true' || !!values.debug
26
+
27
+ // Network interface configuration
28
+ const HOST = process.env['HOST'] || (values.host as string) || 'localhost'
29
+
30
+ interface Client {
31
+ id: string
32
+ isServer: boolean // Flag to identify if this client is the laplace-chat server
33
+ }
34
+
35
+ const clients = new Map<any, Client>()
36
+ let nextClientId = 1
37
+
38
+ const server = Bun.serve<Client, {}>({
39
+ port: 9696,
40
+ hostname: HOST,
41
+ fetch(req, server) {
42
+ // Check if this is the laplace-chat server connecting
43
+ // Format: "laplace-event-bridge-role-server, password123"
44
+ const protocol = req.headers.get('sec-websocket-protocol')
45
+ const protocolParts = protocol ? protocol.split(',') : []
46
+ const role = protocolParts[0]?.trim()
47
+ const password = protocolParts[1]?.trim() // Password for verification
48
+
49
+ const isServer = role === 'laplace-event-bridge-role-server'
50
+
51
+ if (AUTH_TOKEN) {
52
+ if (password !== AUTH_TOKEN) {
53
+ console.log(`Authentication failed: Invalid token for ${isServer ? 'server' : 'client'} connection`)
54
+ return new Response('Unauthorized', { status: 401 })
55
+ }
56
+ }
57
+
58
+ // Upgrade the request to a WebSocket connection
59
+ const success = server.upgrade(req, {
60
+ data: {
61
+ id: `${isServer ? 'server' : 'client'}-${nextClientId++}`,
62
+ isServer,
63
+ },
64
+ })
65
+
66
+ if (!success) {
67
+ return new Response('WebSocket upgrade failed. This is a WebSocket server.', { status: 400 })
68
+ }
69
+
70
+ return undefined
71
+ },
72
+ websocket: {
73
+ open(ws) {
74
+ const clientId = ws.data.id
75
+ const isServer = ws.data.isServer
76
+ clients.set(ws, ws.data)
77
+
78
+ console.log(`Client connected: ${clientId}${isServer ? ' (laplace-chat server)' : ''}`)
79
+
80
+ // Welcome message
81
+ ws.send(
82
+ JSON.stringify({
83
+ type: 'established',
84
+ clientId,
85
+ isServer,
86
+ message: 'Connected to LAPLACE Event bridge',
87
+ })
88
+ )
89
+ },
90
+ message(ws, message) {
91
+ const clientId = ws.data.id
92
+ const isServer = ws.data.isServer
93
+
94
+ try {
95
+ const messageStr = message.toString()
96
+ let parsedMessage: LaplaceEvent
97
+ let broadcastMessage
98
+
99
+ try {
100
+ // Try to parse as JSON
101
+ parsedMessage = JSON.parse(messageStr)
102
+
103
+ if (DEBUG_MODE) {
104
+ console.log(`Received ${parsedMessage.type} from ${clientId}:`, parsedMessage)
105
+ } else {
106
+ console.log(`Received ${parsedMessage.type} from ${clientId}`)
107
+ }
108
+
109
+ // Prepare broadcast message in the same format
110
+ broadcastMessage = JSON.stringify({
111
+ ...parsedMessage,
112
+ source: clientId,
113
+ })
114
+ } catch (e) {
115
+ // Handle as plain text if not JSON
116
+ console.log(`Received message from ${clientId}: ${messageStr}`)
117
+
118
+ // Prepare broadcast message for plain text
119
+ broadcastMessage = JSON.stringify({
120
+ type: 'unknown-message',
121
+ text: messageStr,
122
+ source: clientId,
123
+ timestamp: Date.now(),
124
+ })
125
+ }
126
+
127
+ // Broadcast to all clients EXCEPT the server
128
+ // If the message is from the server, broadcast to all clients
129
+ // If from a client, don't broadcast (or optionally can be enabled)
130
+ if (isServer) {
131
+ // console.log(`Broadcasting message from laplace-chat to all clients`)
132
+
133
+ // Broadcast to all clients except the server
134
+ for (const [client, data] of clients.entries()) {
135
+ if (client !== ws) {
136
+ client.send(broadcastMessage)
137
+ }
138
+ }
139
+
140
+ // Send confirmation back to the server
141
+ ws.send(
142
+ JSON.stringify({
143
+ type: 'broadcast-success',
144
+ clientCount: clients.size - 1, // Excluding the server
145
+ timestamp: Date.now(),
146
+ })
147
+ )
148
+ } else {
149
+ // Optional: Echo back to the client that their message was received
150
+ ws.send(
151
+ JSON.stringify({
152
+ type: 'client-message-received',
153
+ message: 'Message received (client-to-server messages are not relayed)',
154
+ timestamp: Date.now(),
155
+ })
156
+ )
157
+ }
158
+ } catch (error) {
159
+ console.error(`Error processing message from ${clientId}:`, error)
160
+ ws.send(
161
+ JSON.stringify({
162
+ type: 'error',
163
+ message: 'Failed to process your message',
164
+ timestamp: Date.now(),
165
+ })
166
+ )
167
+ }
168
+ },
169
+ close(ws) {
170
+ const clientId = ws.data.id
171
+ const isServer = ws.data.isServer
172
+ clients.delete(ws)
173
+ console.log(`Client disconnected: ${clientId}${isServer ? ' (laplace-chat server)' : ''}`)
174
+ },
175
+ drain(ws) {
176
+ console.log(`WebSocket backpressure: ${ws.getBufferedAmount()}`)
177
+ },
178
+ },
179
+ })
180
+
181
+ // Create a banner display at startup
182
+ function displayBanner() {
183
+ console.log('🌸 LAPLACE Event Bridge Server')
184
+ console.log(`🚀 Server running at http://${server.hostname}:${server.port}`)
185
+ console.log(`🔐 Authentication: ${AUTH_TOKEN ? '✅ Enabled' : '❌ Disabled'}`)
186
+ console.log(`🐛 Debug Mode: ${DEBUG_MODE ? '✅ Enabled' : '❌ Disabled'}`)
187
+ console.log(`⏱️ Started at: ${new Date().toLocaleString()}`)
188
+ console.log(`\nWaiting for connections...\n`)
189
+ }
190
+
191
+ displayBanner()
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@laplace.live/event-bridge-server",
3
3
  "description": "LAPLACE Event Bridge Server",
4
- "version": "0.2.0",
4
+ "version": "0.2.2",
5
5
  "license": "AGPL-3.0",
6
6
  "type": "module",
7
7
  "module": "index.ts",
package/.env DELETED
@@ -1 +0,0 @@
1
- # LAPLACE_EVENT_BRIDGE_AUTH=laplace