bxo 0.0.9 โ†’ 0.0.10-dev.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.
@@ -127,101 +127,127 @@ async function main() {
127
127
  `, 200);
128
128
  });
129
129
 
130
- // WebSocket route with enhanced client identification
130
+ // WebSocket route with enhanced client identification and typed interface
131
131
  app.ws("/ws", {
132
132
  open(ws) {
133
- const clientInfo = ws.data;
133
+ const data = ws.data; // Now fully typed with WebSocketData interface
134
134
  console.log("๐Ÿ”Œ WebSocket connection opened:");
135
- console.log(` ๐Ÿ†” Client ID: ${clientInfo.id}`);
136
- console.log(` ๐Ÿ”— Connection ID: ${clientInfo.connectionId}`);
137
- console.log(` ๐ŸŒ Client IP: ${clientInfo.ip}`);
138
- console.log(` ๐Ÿ–ฅ๏ธ User Agent: ${clientInfo.userAgent}`);
139
- console.log(` ๐ŸŽฏ Origin: ${clientInfo.origin}`);
140
- console.log(` ๐Ÿ  Host: ${clientInfo.host}`);
141
- console.log(` ๐Ÿ“ Path: ${clientInfo.path}`);
142
- console.log(` ๐Ÿช Cookies:`, clientInfo.cookies);
143
- console.log(` ๐Ÿ” Search Params:`, clientInfo.searchParams);
144
- console.log(` ๐Ÿ” Authorization:`, clientInfo.authorization || 'None');
145
-
146
- // Check for authentication
147
- if (clientInfo.authorization) {
135
+ console.log(` ๐Ÿ†” Client ID: ${data.id}`);
136
+ console.log(` ๐Ÿ”— Connection ID: ${data.connectionId}`);
137
+ console.log(` ๐ŸŒ Client IP: ${data.ip}`);
138
+ console.log(` ๐Ÿ–ฅ๏ธ User Agent: ${data.userAgent}`);
139
+ console.log(` ๐ŸŽฏ Origin: ${data.origin}`);
140
+ console.log(` ๐Ÿ  Host: ${data.host}`);
141
+ console.log(` ๐Ÿ“ Path: ${data.path}`);
142
+ console.log(` ๐Ÿช Cookies:`, data.cookies);
143
+ console.log(` ๐Ÿ” Search Params:`, data.searchParams);
144
+ console.log(` ๐Ÿ” Authorization:`, data.authorization || 'None');
145
+
146
+ // Use direct property access
147
+ console.log(` ๐Ÿช Session Cookie:`, data.cookies.sessionId);
148
+ console.log(` ๐Ÿ” Room Param:`, data.searchParams.room);
149
+ console.log(` ๐Ÿ‘ค Username:`, data.searchParams.user || data.searchParams.username);
150
+ console.log(` ๐Ÿ  Room:`, data.searchParams.room);
151
+ console.log(` ๐Ÿ” Has Auth:`, !!(data.authorization || data.searchParams.token || data.searchParams.auth));
152
+ console.log(` ๐Ÿ”‘ Auth Type:`, data.authorization ? (data.authorization.toLowerCase().startsWith('bearer ') ? 'bearer' : 'basic') : 'none');
153
+ console.log(` ๐ŸŽซ Token:`, data.searchParams.token || data.searchParams.auth);
154
+
155
+ // Check for authentication using direct property access
156
+ if (data.authorization || data.searchParams.token || data.searchParams.auth) {
148
157
  console.log(` โœ… Authenticated user detected`);
149
- ws.send(`Welcome authenticated user! Your WebSocket ID is: ${clientInfo.id}`);
150
- } else if (clientInfo.searchParams.token || clientInfo.searchParams.auth) {
151
- console.log(` ๐Ÿ”‘ Token-based auth detected`);
152
- ws.send(`Welcome! Token detected. Your WebSocket ID is: ${clientInfo.id}`);
158
+ ws.send(`Welcome authenticated user! Your WebSocket ID is: ${data.id}`);
153
159
  } else {
154
- ws.send(`Welcome! Your WebSocket ID is: ${clientInfo.id}`);
160
+ ws.send(`Welcome! Your WebSocket ID is: ${data.id}`);
155
161
  }
156
162
  },
157
163
 
158
164
  message(ws, message) {
159
- const clientInfo = ws.data;
160
- console.log(`๐Ÿ’ฌ Message from ${clientInfo.id} (${clientInfo.ip}):`, message);
161
- console.log(` ๐Ÿช Client cookies:`, clientInfo.cookies);
162
- console.log(` ๐Ÿ” Search params:`, clientInfo.searchParams);
163
- console.log(` ๐Ÿ” Auth:`, clientInfo.authorization || 'None');
165
+ const data = ws.data; // Fully typed WebSocketData
166
+ console.log(`๐Ÿ’ฌ Message from ${data.id} (${data.ip}):`, message);
167
+ console.log(` ๐Ÿช Client cookies:`, data.cookies);
168
+ console.log(` ๐Ÿ” Search params:`, data.searchParams);
169
+ console.log(` ๐Ÿ” Auth:`, data.authorization || 'None');
170
+
171
+ // Use direct property access
172
+ const username = data.searchParams.user || data.searchParams.username || 'Anonymous';
173
+ const room = data.searchParams.room;
174
+ const sessionId = data.cookies.sessionId;
175
+
176
+ console.log(` ๐Ÿ‘ค Username: ${username}`);
177
+ console.log(` ๐Ÿ  Room: ${room || 'None'}`);
178
+ console.log(` ๐Ÿช Session: ${sessionId || 'None'}`);
164
179
 
165
180
  // Echo the message back with client ID and context
166
- let response = `[${clientInfo.id}] Echo: ${message}`;
181
+ let response = `[${data.id}] Echo: ${message}`;
167
182
 
168
- // Add context based on search params
169
- if (clientInfo.searchParams.room) {
170
- response += ` (Room: ${clientInfo.searchParams.room})`;
183
+ // Add context using direct property access
184
+ if (room) {
185
+ response += ` (Room: ${room})`;
171
186
  }
172
- if (clientInfo.searchParams.user) {
173
- response += ` (User: ${clientInfo.searchParams.user})`;
187
+ if (username && username !== 'Anonymous') {
188
+ response += ` (User: ${username})`;
174
189
  }
175
190
 
176
191
  ws.send(response);
177
192
  },
178
193
 
179
194
  close(ws, code, reason) {
180
- const clientInfo = ws.data;
181
- console.log(`โŒ WebSocket connection closed for ${clientInfo.id}: ${code} ${reason}`);
195
+ const data = ws.data;
196
+ console.log(`โŒ WebSocket connection closed for ${data.id}: ${code} ${reason}`);
182
197
  },
183
198
 
184
199
  ping(ws, data) {
185
- const clientInfo = ws.data;
186
- console.log(`๐Ÿ“ Ping received from ${clientInfo.id}:`, data);
200
+ const wsData = ws.data;
201
+ console.log(`๐Ÿ“ Ping received from ${wsData.id}:`, data);
187
202
  },
188
203
 
189
204
  pong(ws, data) {
190
- const clientInfo = ws.data;
191
- console.log(`๐Ÿ“ Pong received from ${clientInfo.id}:`, data);
205
+ const wsData = ws.data;
206
+ console.log(`๐Ÿ“ Pong received from ${wsData.id}:`, data);
192
207
  }
193
208
  });
194
209
 
195
- // Chat room WebSocket with client identification
210
+ // Chat room WebSocket with typed client identification
196
211
  app.ws("/chat/:room", {
197
212
  open(ws) {
198
- const clientInfo = ws.data;
199
- const room = clientInfo.path.split('/').pop() || 'unknown';
213
+ const data = ws.data; // Fully typed WebSocketData
214
+ const room = data.path.split('/').pop() || 'unknown';
200
215
  console.log(`๐Ÿ  Chat room connection opened for room: ${room}`);
201
- console.log(` ๐Ÿ†” Client: ${clientInfo.id} (${clientInfo.ip})`);
202
- console.log(` ๐Ÿช Cookies:`, clientInfo.cookies);
203
- console.log(` ๐Ÿ” Search Params:`, clientInfo.searchParams);
204
- console.log(` ๐Ÿ” Authorization:`, clientInfo.authorization || 'None');
205
-
206
- // Check for user info in search params
207
- const username = clientInfo.searchParams.user || clientInfo.searchParams.username || 'Anonymous';
208
- ws.send(`Welcome to chat room: ${room}! Your ID is: ${clientInfo.id}, Username: ${username}`);
216
+ console.log(` ๐Ÿ†” Client: ${data.id} (${data.ip})`);
217
+ console.log(` ๐Ÿช Cookies:`, data.cookies);
218
+ console.log(` ๐Ÿ” Search Params:`, data.searchParams);
219
+ console.log(` ๐Ÿ” Authorization:`, data.authorization || 'None');
220
+
221
+ // Use direct property access
222
+ const username = data.searchParams.user || data.searchParams.username || 'Anonymous';
223
+ const sessionId = data.cookies.sessionId;
224
+ const hasAuth = !!(data.authorization || data.searchParams.token || data.searchParams.auth);
225
+
226
+ console.log(` ๐Ÿ‘ค Username: ${username}`);
227
+ console.log(` ๐Ÿช Session: ${sessionId || 'None'}`);
228
+ console.log(` ๐Ÿ” Authenticated: ${hasAuth}`);
229
+
230
+ ws.send(`Welcome to chat room: ${room}! Your ID is: ${data.id}, Username: ${username}`);
209
231
  },
210
232
 
211
233
  message(ws, message) {
212
- const clientInfo = ws.data;
213
- const room = clientInfo.path.split('/').pop() || 'unknown';
214
- const username = clientInfo.searchParams.user || clientInfo.searchParams.username || 'Anonymous';
215
- console.log(`๐Ÿ’ฌ Message in room ${room} from ${clientInfo.id} (${username}):`, message);
216
- console.log(` ๐Ÿช Client cookies:`, clientInfo.cookies);
217
- console.log(` ๐Ÿ” Search params:`, clientInfo.searchParams);
218
- ws.send(`[${room}] [${username}] [${clientInfo.id}] Echo: ${message}`);
234
+ const data = ws.data; // Fully typed WebSocketData
235
+ const room = data.path.split('/').pop() || 'unknown';
236
+ const username = data.searchParams.user || data.searchParams.username || 'Anonymous';
237
+ const sessionId = data.cookies.sessionId;
238
+
239
+ console.log(`๐Ÿ’ฌ Message in room ${room} from ${data.id} (${username}):`, message);
240
+ console.log(` ๐Ÿช Client cookies:`, data.cookies);
241
+ console.log(` ๐Ÿ” Search params:`, data.searchParams);
242
+ console.log(` ๐Ÿช Session: ${sessionId || 'None'}`);
243
+
244
+ ws.send(`[${room}] [${username}] [${data.id}] Echo: ${message}`);
219
245
  },
220
246
 
221
247
  close(ws, code, reason) {
222
- const clientInfo = ws.data;
223
- const room = clientInfo.path.split('/').pop() || 'unknown';
224
- console.log(`โŒ Chat room connection closed for room ${room} (${clientInfo.id}): ${code} ${reason}`);
248
+ const data = ws.data;
249
+ const room = data.path.split('/').pop() || 'unknown';
250
+ console.log(`โŒ Chat room connection closed for room ${room} (${data.id}): ${code} ${reason}`);
225
251
  }
226
252
  });
227
253
 
@@ -230,12 +256,18 @@ async function main() {
230
256
  console.log(`๐Ÿ”Œ WebSocket available at ws://localhost:${app.server?.port}/ws`);
231
257
  console.log(`๐Ÿ’ฌ Chat WebSocket available at ws://localhost:${app.server?.port}/chat/:room`);
232
258
  console.log(`\n๐Ÿ“ Features demonstrated:`);
233
- console.log(` โ€ข ws.id - Short, unique client identifier`);
259
+ console.log(` โ€ข ws.data.id - Short, unique client identifier`);
234
260
  console.log(` โ€ข ws.data.connectionId - Detailed connection ID`);
235
261
  console.log(` โ€ข ws.data.cookies - Parsed cookies from handshake`);
236
262
  console.log(` โ€ข ws.data.searchParams - Query parameters from URL`);
237
263
  console.log(` โ€ข ws.data.authorization - Authorization header`);
238
264
  console.log(` โ€ข Client IP, User Agent, Origin tracking`);
265
+ console.log(`\n๐Ÿ”ง Direct Property Access:`);
266
+ console.log(` โ€ข ws.data.cookies.name - Get specific cookie`);
267
+ console.log(` โ€ข ws.data.searchParams.name - Get specific search param`);
268
+ console.log(` โ€ข ws.data.authorization - Check authorization header`);
269
+ console.log(` โ€ข ws.data.id - Short client identifier`);
270
+ console.log(` โ€ข ws.data.connectionId - Detailed connection ID`);
239
271
  console.log(`\n๐Ÿงช Test URLs:`);
240
272
  console.log(` โ€ข Basic: ws://localhost:${app.server?.port}/ws`);
241
273
  console.log(` โ€ข With params: ws://localhost:${app.server?.port}/ws?room=test&user=john&theme=dark`);
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  ".": "./src/index.ts",
6
6
  "./plugins": "./plugins/index.ts"
7
7
  },
8
- "version": "0.0.9",
8
+ "version": "0.0.10-dev.2",
9
9
  "type": "module",
10
10
  "devDependencies": {
11
11
  "@types/bun": "latest"
package/src/index.ts CHANGED
@@ -106,8 +106,14 @@ export type WebSocketClientInfo = {
106
106
  authorization?: string; // Authorization header (Bearer token, Basic auth, etc.)
107
107
  };
108
108
 
109
+ // WebSocket data interface - this is what you get when accessing ws.data
110
+ export interface WebSocketData extends WebSocketClientInfo {
111
+ // Simple interface with just the data properties
112
+ // No convenience methods - use direct property access
113
+ }
114
+
109
115
  // WebSocket handler types
110
- export type WebSocketHandler<T = any> = {
116
+ export type WebSocketHandler<T = WebSocketData> = {
111
117
  message?(ws: Bun.ServerWebSocket<T>, message: string | Buffer): void | Promise<void>;
112
118
  open?(ws: Bun.ServerWebSocket<T>): void | Promise<void>;
113
119
  close?(ws: Bun.ServerWebSocket<T>, code: number, reason: string): void | Promise<void>;
@@ -450,22 +456,22 @@ export default class BXO {
450
456
 
451
457
  // Create WebSocket configuration if we have WebSocket routes
452
458
  const websocketConfig = hasWebSocketRoutes ? {
453
- message: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, message: string | Buffer) => {
459
+ message: (ws: Bun.ServerWebSocket<WebSocketData>, message: string | Buffer) => {
454
460
  this.handleWebSocketMessage(ws, message);
455
461
  },
456
- open: (ws: Bun.ServerWebSocket<WebSocketClientInfo>) => {
462
+ open: (ws: Bun.ServerWebSocket<WebSocketData>) => {
457
463
  this.handleWebSocketOpen(ws);
458
464
  },
459
- close: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, code: number, reason: string) => {
465
+ close: (ws: Bun.ServerWebSocket<WebSocketData>, code: number, reason: string) => {
460
466
  this.handleWebSocketClose(ws, code, reason);
461
467
  },
462
- drain: (ws: Bun.ServerWebSocket<WebSocketClientInfo>) => {
468
+ drain: (ws: Bun.ServerWebSocket<WebSocketData>) => {
463
469
  this.handleWebSocketDrain(ws);
464
470
  },
465
- ping: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer) => {
471
+ ping: (ws: Bun.ServerWebSocket<WebSocketData>, data: Buffer) => {
466
472
  this.handleWebSocketPing(ws, data);
467
473
  },
468
- pong: (ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer) => {
474
+ pong: (ws: Bun.ServerWebSocket<WebSocketData>, data: Buffer) => {
469
475
  this.handleWebSocketPong(ws, data);
470
476
  }
471
477
  } : undefined;
@@ -502,7 +508,7 @@ export default class BXO {
502
508
  }
503
509
  }
504
510
 
505
- const clientInfo = {
511
+ const baseClientInfo = {
506
512
  id: shortId, // Short, easy-to-use ID
507
513
  path: url.pathname,
508
514
  ip: req.headers.get("x-forwarded-for") ||
@@ -516,6 +522,11 @@ export default class BXO {
516
522
  searchParams: searchParams, // Query parameters from URL
517
523
  authorization: authHeader || undefined // Authorization header
518
524
  };
525
+
526
+ // Create simple WebSocket data object
527
+ const clientInfo: WebSocketData = {
528
+ ...baseClientInfo
529
+ };
519
530
 
520
531
  const success = server.upgrade(req, {
521
532
  data: clientInfo
@@ -583,7 +594,7 @@ export default class BXO {
583
594
  return null;
584
595
  }
585
596
 
586
- private handleWebSocketMessage(ws: Bun.ServerWebSocket<WebSocketClientInfo>, message: string | Buffer): void {
597
+ private handleWebSocketMessage(ws: Bun.ServerWebSocket<WebSocketData>, message: string | Buffer): void {
587
598
  const route = this.findWebSocketRoute(ws.data?.path || "");
588
599
  if (route?.websocketHandler?.message) {
589
600
  try {
@@ -594,7 +605,7 @@ export default class BXO {
594
605
  }
595
606
  }
596
607
 
597
- private handleWebSocketOpen(ws: Bun.ServerWebSocket<WebSocketClientInfo>): void {
608
+ private handleWebSocketOpen(ws: Bun.ServerWebSocket<WebSocketData>): void {
598
609
  const route = this.findWebSocketRoute(ws.data?.path || "");
599
610
  if (route?.websocketHandler?.open) {
600
611
  try {
@@ -605,7 +616,7 @@ export default class BXO {
605
616
  }
606
617
  }
607
618
 
608
- private handleWebSocketClose(ws: Bun.ServerWebSocket<WebSocketClientInfo>, code: number, reason: string): void {
619
+ private handleWebSocketClose(ws: Bun.ServerWebSocket<WebSocketData>, code: number, reason: string): void {
609
620
  const route = this.findWebSocketRoute(ws.data?.path || "");
610
621
  if (route?.websocketHandler?.close) {
611
622
  try {
@@ -616,7 +627,7 @@ export default class BXO {
616
627
  }
617
628
  }
618
629
 
619
- private handleWebSocketDrain(ws: Bun.ServerWebSocket<WebSocketClientInfo>): void {
630
+ private handleWebSocketDrain(ws: Bun.ServerWebSocket<WebSocketData>): void {
620
631
  const route = this.findWebSocketRoute(ws.data?.path || "");
621
632
  if (route?.websocketHandler?.drain) {
622
633
  try {
@@ -627,7 +638,7 @@ export default class BXO {
627
638
  }
628
639
  }
629
640
 
630
- private handleWebSocketPing(ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer): void {
641
+ private handleWebSocketPing(ws: Bun.ServerWebSocket<WebSocketData>, data: Buffer): void {
631
642
  const route = this.findWebSocketRoute(ws.data?.path || "");
632
643
  if (route?.websocketHandler?.ping) {
633
644
  try {
@@ -638,7 +649,7 @@ export default class BXO {
638
649
  }
639
650
  }
640
651
 
641
- private handleWebSocketPong(ws: Bun.ServerWebSocket<WebSocketClientInfo>, data: Buffer): void {
652
+ private handleWebSocketPong(ws: Bun.ServerWebSocket<WebSocketData>, data: Buffer): void {
642
653
  const route = this.findWebSocketRoute(ws.data?.path || "");
643
654
  if (route?.websocketHandler?.pong) {
644
655
  try {
@@ -1,68 +0,0 @@
1
- // Comprehensive test for enhanced WebSocket client identification
2
- console.log('๐Ÿงช Testing Enhanced WebSocket Client Identification...\n');
3
-
4
- // Test 1: Basic WebSocket connection
5
- console.log('1. Testing basic WebSocket connection');
6
- const ws1 = new WebSocket('ws://localhost:3000/ws');
7
-
8
- ws1.onopen = function() {
9
- console.log('โœ“ Connected to basic WebSocket');
10
- ws1.send('Hello from basic connection!');
11
- };
12
-
13
- ws1.onmessage = function(event) {
14
- console.log('โœ“ Received:', event.data);
15
- ws1.close();
16
- };
17
-
18
- ws1.onclose = function() {
19
- console.log('โœ“ Basic connection closed\n');
20
-
21
- // Test 2: WebSocket with search parameters
22
- console.log('2. Testing WebSocket with search parameters');
23
- const ws2 = new WebSocket('ws://localhost:3000/ws?room=test&user=john&theme=dark&token=abc123');
24
-
25
- ws2.onopen = function() {
26
- console.log('โœ“ Connected with search params');
27
- ws2.send('Hello from connection with params!');
28
- };
29
-
30
- ws2.onmessage = function(event) {
31
- console.log('โœ“ Received:', event.data);
32
- ws2.close();
33
- };
34
-
35
- ws2.onclose = function() {
36
- console.log('โœ“ Search params connection closed\n');
37
-
38
- // Test 3: Chat room with search parameters
39
- console.log('3. Testing chat room with search parameters');
40
- const ws3 = new WebSocket('ws://localhost:3000/chat/general?user=alice&theme=light&role=moderator');
41
-
42
- ws3.onopen = function() {
43
- console.log('โœ“ Connected to chat room with params');
44
- ws3.send('Hello from chat room!');
45
- };
46
-
47
- ws3.onmessage = function(event) {
48
- console.log('โœ“ Received:', event.data);
49
- ws3.close();
50
- };
51
-
52
- ws3.onclose = function() {
53
- console.log('โœ“ Chat room connection closed');
54
- console.log('\nโœ… All tests completed! Check the server logs to see:');
55
- console.log(' โ€ข ws.id - Short client identifier');
56
- console.log(' โ€ข ws.data.searchParams - Query parameters');
57
- console.log(' โ€ข ws.data.cookies - Parsed cookies');
58
- console.log(' โ€ข ws.data.authorization - Auth header');
59
- console.log(' โ€ข Client IP and other identification info');
60
- process.exit(0);
61
- };
62
- };
63
- };
64
-
65
- ws1.onerror = function(error) {
66
- console.error('โŒ WebSocket error:', error);
67
- process.exit(1);
68
- };