bitchat-node 0.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.
Files changed (102) hide show
  1. package/README.md +223 -0
  2. package/dist/bin/bitchat.d.ts +7 -0
  3. package/dist/bin/bitchat.d.ts.map +1 -0
  4. package/dist/bin/bitchat.js +69 -0
  5. package/dist/bin/bitchat.js.map +1 -0
  6. package/dist/client.d.ts +77 -0
  7. package/dist/client.d.ts.map +1 -0
  8. package/dist/client.js +411 -0
  9. package/dist/client.js.map +1 -0
  10. package/dist/crypto/index.d.ts +6 -0
  11. package/dist/crypto/index.d.ts.map +1 -0
  12. package/dist/crypto/index.js +6 -0
  13. package/dist/crypto/index.js.map +1 -0
  14. package/dist/crypto/noise.d.ts +72 -0
  15. package/dist/crypto/noise.d.ts.map +1 -0
  16. package/dist/crypto/noise.js +470 -0
  17. package/dist/crypto/noise.js.map +1 -0
  18. package/dist/crypto/signing.d.ts +34 -0
  19. package/dist/crypto/signing.d.ts.map +1 -0
  20. package/dist/crypto/signing.js +56 -0
  21. package/dist/crypto/signing.js.map +1 -0
  22. package/dist/index.d.ts +32 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +48 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/mesh/deduplicator.d.ts +48 -0
  27. package/dist/mesh/deduplicator.d.ts.map +1 -0
  28. package/dist/mesh/deduplicator.js +107 -0
  29. package/dist/mesh/deduplicator.js.map +1 -0
  30. package/dist/mesh/index.d.ts +6 -0
  31. package/dist/mesh/index.d.ts.map +1 -0
  32. package/dist/mesh/index.js +6 -0
  33. package/dist/mesh/index.js.map +1 -0
  34. package/dist/mesh/router.d.ts +90 -0
  35. package/dist/mesh/router.d.ts.map +1 -0
  36. package/dist/mesh/router.js +204 -0
  37. package/dist/mesh/router.js.map +1 -0
  38. package/dist/protocol/binary.d.ts +37 -0
  39. package/dist/protocol/binary.d.ts.map +1 -0
  40. package/dist/protocol/binary.js +310 -0
  41. package/dist/protocol/binary.js.map +1 -0
  42. package/dist/protocol/constants.d.ts +30 -0
  43. package/dist/protocol/constants.d.ts.map +1 -0
  44. package/dist/protocol/constants.js +37 -0
  45. package/dist/protocol/constants.js.map +1 -0
  46. package/dist/protocol/index.d.ts +8 -0
  47. package/dist/protocol/index.d.ts.map +1 -0
  48. package/dist/protocol/index.js +8 -0
  49. package/dist/protocol/index.js.map +1 -0
  50. package/dist/protocol/packets.d.ts +38 -0
  51. package/dist/protocol/packets.d.ts.map +1 -0
  52. package/dist/protocol/packets.js +177 -0
  53. package/dist/protocol/packets.js.map +1 -0
  54. package/dist/protocol/types.d.ts +134 -0
  55. package/dist/protocol/types.d.ts.map +1 -0
  56. package/dist/protocol/types.js +108 -0
  57. package/dist/protocol/types.js.map +1 -0
  58. package/dist/session/index.d.ts +5 -0
  59. package/dist/session/index.d.ts.map +1 -0
  60. package/dist/session/index.js +5 -0
  61. package/dist/session/index.js.map +1 -0
  62. package/dist/session/manager.d.ts +113 -0
  63. package/dist/session/manager.d.ts.map +1 -0
  64. package/dist/session/manager.js +371 -0
  65. package/dist/session/manager.js.map +1 -0
  66. package/dist/transport/ble.d.ts +92 -0
  67. package/dist/transport/ble.d.ts.map +1 -0
  68. package/dist/transport/ble.js +434 -0
  69. package/dist/transport/ble.js.map +1 -0
  70. package/dist/transport/index.d.ts +5 -0
  71. package/dist/transport/index.d.ts.map +1 -0
  72. package/dist/transport/index.js +5 -0
  73. package/dist/transport/index.js.map +1 -0
  74. package/dist/ui/index.d.ts +2 -0
  75. package/dist/ui/index.d.ts.map +1 -0
  76. package/dist/ui/index.js +2 -0
  77. package/dist/ui/index.js.map +1 -0
  78. package/dist/ui/server.d.ts +16 -0
  79. package/dist/ui/server.d.ts.map +1 -0
  80. package/dist/ui/server.js +510 -0
  81. package/dist/ui/server.js.map +1 -0
  82. package/package.json +79 -0
  83. package/src/bin/bitchat.ts +87 -0
  84. package/src/client.ts +519 -0
  85. package/src/crypto/index.ts +22 -0
  86. package/src/crypto/noise.ts +574 -0
  87. package/src/crypto/signing.ts +66 -0
  88. package/src/index.ts +95 -0
  89. package/src/mesh/deduplicator.ts +129 -0
  90. package/src/mesh/index.ts +6 -0
  91. package/src/mesh/router.ts +258 -0
  92. package/src/protocol/binary.ts +345 -0
  93. package/src/protocol/constants.ts +43 -0
  94. package/src/protocol/index.ts +15 -0
  95. package/src/protocol/packets.ts +223 -0
  96. package/src/protocol/types.ts +182 -0
  97. package/src/session/index.ts +9 -0
  98. package/src/session/manager.ts +476 -0
  99. package/src/transport/ble.ts +553 -0
  100. package/src/transport/index.ts +10 -0
  101. package/src/ui/index.ts +1 -0
  102. package/src/ui/server.ts +569 -0
@@ -0,0 +1,510 @@
1
+ /**
2
+ * Bitchat Web UI Server
3
+ * Simple HTTP + WebSocket server for testing
4
+ */
5
+ import { createServer } from 'node:http';
6
+ import { WebSocket, WebSocketServer } from 'ws';
7
+ const HTML = `<!DOCTYPE html>
8
+ <html>
9
+ <head>
10
+ <meta charset="UTF-8">
11
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
12
+ <title>Bitchat Node</title>
13
+ <style>
14
+ * { box-sizing: border-box; margin: 0; padding: 0; }
15
+ body {
16
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
17
+ background: #1a1a2e; color: #eee; height: 100vh; display: flex; flex-direction: column;
18
+ }
19
+ header {
20
+ background: #16213e; padding: 16px 20px; border-bottom: 1px solid #0f3460;
21
+ display: flex; justify-content: space-between; align-items: center;
22
+ }
23
+ header h1 { font-size: 18px; font-weight: 600; }
24
+ .status { font-size: 12px; color: #888; }
25
+ .status.connected { color: #4ade80; }
26
+ .peers { font-size: 12px; color: #60a5fa; margin-left: 16px; }
27
+ main { flex: 1; display: flex; overflow: hidden; }
28
+ .messages {
29
+ flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 8px;
30
+ }
31
+ .message {
32
+ background: #16213e; padding: 12px 16px; border-radius: 12px; max-width: 80%;
33
+ animation: fadeIn 0.2s ease;
34
+ }
35
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(8px); } }
36
+ .message.mine { background: #0f3460; align-self: flex-end; }
37
+ .message.private { border-left: 3px solid #f472b6; }
38
+ .message .meta { font-size: 11px; color: #888; margin-bottom: 4px; }
39
+ .message .meta .nickname { color: #60a5fa; font-weight: 500; }
40
+ .message .meta .private-badge { color: #f472b6; margin-left: 8px; }
41
+ .message .content { line-height: 1.4; word-wrap: break-word; }
42
+ .system {
43
+ text-align: center; font-size: 12px; color: #666; padding: 8px;
44
+ }
45
+ footer { background: #16213e; padding: 16px; border-top: 1px solid #0f3460; }
46
+ .input-row { display: flex; gap: 8px; }
47
+ input[type="text"] {
48
+ flex: 1; background: #1a1a2e; border: 1px solid #0f3460; border-radius: 8px;
49
+ padding: 12px 16px; color: #eee; font-size: 14px; outline: none;
50
+ }
51
+ input[type="text"]:focus { border-color: #3b82f6; }
52
+ input[type="text"]::placeholder { color: #555; }
53
+ button {
54
+ background: #3b82f6; color: white; border: none; border-radius: 8px;
55
+ padding: 12px 24px; font-size: 14px; font-weight: 500; cursor: pointer;
56
+ transition: background 0.2s;
57
+ }
58
+ button:hover { background: #2563eb; }
59
+ button:disabled { background: #374151; cursor: not-allowed; }
60
+ .peers-panel {
61
+ width: 200px; background: #16213e; border-left: 1px solid #0f3460;
62
+ padding: 16px; overflow-y: auto;
63
+ }
64
+ .peers-panel h3 { font-size: 12px; color: #888; margin-bottom: 12px; text-transform: uppercase; }
65
+ .peer {
66
+ padding: 8px 12px; background: #1a1a2e; border-radius: 6px; margin-bottom: 8px;
67
+ font-size: 13px; cursor: pointer; transition: background 0.2s;
68
+ }
69
+ .peer:hover { background: #0f3460; }
70
+ .peer .peer-id { font-size: 10px; color: #666; margin-top: 2px; font-family: monospace; }
71
+ .peer.selected { background: #3b82f6; }
72
+ </style>
73
+ </head>
74
+ <body>
75
+ <header>
76
+ <div>
77
+ <h1>🔗 Bitchat Node</h1>
78
+ <span class="status" id="status">Connecting...</span>
79
+ <span class="peers" id="peer-count"></span>
80
+ </div>
81
+ <div id="my-info" style="font-size: 12px; color: #888;"></div>
82
+ </header>
83
+ <main>
84
+ <div class="messages" id="messages"></div>
85
+ <div class="peers-panel">
86
+ <h3>Peers</h3>
87
+ <div id="peers-list"></div>
88
+ </div>
89
+ </main>
90
+ <footer>
91
+ <div class="input-row">
92
+ <input type="text" id="input" placeholder="Type a message..." autocomplete="off">
93
+ <button id="send">Send</button>
94
+ </div>
95
+ </footer>
96
+ <script>
97
+ const messagesEl = document.getElementById('messages');
98
+ const inputEl = document.getElementById('input');
99
+ const sendBtn = document.getElementById('send');
100
+ const statusEl = document.getElementById('status');
101
+ const peerCountEl = document.getElementById('peer-count');
102
+ const peersListEl = document.getElementById('peers-list');
103
+ const myInfoEl = document.getElementById('my-info');
104
+
105
+ let ws;
106
+ let myPeerID = '';
107
+ let selectedPeer = null;
108
+ const peers = new Map();
109
+
110
+ function connect() {
111
+ ws = new WebSocket('ws://' + location.host + '/ws');
112
+
113
+ ws.onopen = () => {
114
+ statusEl.textContent = 'Connected';
115
+ statusEl.className = 'status connected';
116
+ };
117
+
118
+ ws.onclose = () => {
119
+ statusEl.textContent = 'Disconnected';
120
+ statusEl.className = 'status';
121
+ setTimeout(connect, 2000);
122
+ };
123
+
124
+ ws.onmessage = (e) => {
125
+ const msg = JSON.parse(e.data);
126
+ handleMessage(msg);
127
+ };
128
+ }
129
+
130
+ function handleMessage(msg) {
131
+ switch (msg.type) {
132
+ case 'init':
133
+ myPeerID = msg.peerID;
134
+ myInfoEl.textContent = msg.nickname + ' · ' + msg.peerID.slice(0, 8) + '...';
135
+ break;
136
+
137
+ case 'message':
138
+ addMessage(msg.message);
139
+ break;
140
+
141
+ case 'peer:connected':
142
+ peers.set(msg.peer.peerID, msg.peer);
143
+ updatePeersList();
144
+ addSystem(msg.peer.nickname + ' joined the mesh');
145
+ break;
146
+
147
+ case 'peer:disconnected':
148
+ const peer = peers.get(msg.peerID);
149
+ peers.delete(msg.peerID);
150
+ updatePeersList();
151
+ if (peer) addSystem(peer.nickname + ' left the mesh');
152
+ break;
153
+
154
+ case 'peers':
155
+ peers.clear();
156
+ msg.peers.forEach(p => peers.set(p.peerID, p));
157
+ updatePeersList();
158
+ break;
159
+
160
+ case 'sent':
161
+ // Could update delivery status
162
+ break;
163
+
164
+ case 'error':
165
+ addSystem('Error: ' + msg.error);
166
+ break;
167
+ }
168
+ }
169
+
170
+ function addMessage(msg) {
171
+ const div = document.createElement('div');
172
+ div.className = 'message' + (msg.sender === myPeerID ? ' mine' : '') + (msg.isPrivate ? ' private' : '');
173
+ div.innerHTML =
174
+ '<div class="meta">' +
175
+ '<span class="nickname">' + escapeHtml(msg.senderNickname) + '</span> · ' +
176
+ new Date(msg.timestamp).toLocaleTimeString() +
177
+ (msg.isPrivate ? '<span class="private-badge">private</span>' : '') +
178
+ '</div>' +
179
+ '<div class="content">' + escapeHtml(msg.content) + '</div>';
180
+ messagesEl.appendChild(div);
181
+ messagesEl.scrollTop = messagesEl.scrollHeight;
182
+ }
183
+
184
+ function addSystem(text) {
185
+ const div = document.createElement('div');
186
+ div.className = 'system';
187
+ div.textContent = text;
188
+ messagesEl.appendChild(div);
189
+ messagesEl.scrollTop = messagesEl.scrollHeight;
190
+ }
191
+
192
+ function updatePeersList() {
193
+ peerCountEl.textContent = peers.size + ' peer' + (peers.size !== 1 ? 's' : '');
194
+ peersListEl.innerHTML = '';
195
+ peers.forEach((peer, id) => {
196
+ const div = document.createElement('div');
197
+ div.className = 'peer' + (selectedPeer === id ? ' selected' : '');
198
+ div.innerHTML =
199
+ '<div>' + escapeHtml(peer.nickname) + '</div>' +
200
+ '<div class="peer-id">' + id.slice(0, 12) + '...</div>';
201
+ div.onclick = () => {
202
+ selectedPeer = selectedPeer === id ? null : id;
203
+ updatePeersList();
204
+ inputEl.placeholder = selectedPeer ? 'Private message to ' + peer.nickname + '...' : 'Type a message...';
205
+ };
206
+ peersListEl.appendChild(div);
207
+ });
208
+ }
209
+
210
+ function send() {
211
+ const text = inputEl.value.trim();
212
+ if (!text) return;
213
+
214
+ if (!ws || ws.readyState !== WebSocket.OPEN) {
215
+ addSystem('Not connected - please wait');
216
+ return;
217
+ }
218
+
219
+ // Show our own message immediately
220
+ addMessage({
221
+ id: Date.now().toString(),
222
+ sender: myPeerID,
223
+ senderNickname: 'me',
224
+ content: text,
225
+ timestamp: new Date().toISOString(),
226
+ isPrivate: !!selectedPeer
227
+ });
228
+
229
+ ws.send(JSON.stringify({
230
+ type: 'send',
231
+ text: text,
232
+ to: selectedPeer || null
233
+ }));
234
+
235
+ inputEl.value = '';
236
+ }
237
+
238
+ function escapeHtml(text) {
239
+ const div = document.createElement('div');
240
+ div.textContent = text;
241
+ return div.innerHTML;
242
+ }
243
+
244
+ sendBtn.onclick = send;
245
+ inputEl.onkeydown = (e) => { if (e.key === 'Enter') send(); };
246
+
247
+ connect();
248
+ </script>
249
+ </body>
250
+ </html>`;
251
+ /**
252
+ * Start a web UI server for the Bitchat client
253
+ */
254
+ export function startUIServer(client, config) {
255
+ const { port } = config;
256
+ const clients = new Set();
257
+ // Message store for polling (keep last 100 messages)
258
+ const messageStore = [];
259
+ const MAX_MESSAGES = 100;
260
+ // Registered webhooks
261
+ const webhooks = [];
262
+ if (config.webhookUrl) {
263
+ webhooks.push(config.webhookUrl);
264
+ }
265
+ // Helper to parse JSON body
266
+ const parseBody = (req) => {
267
+ return new Promise((resolve, reject) => {
268
+ let body = '';
269
+ req.on('data', (chunk) => (body += chunk));
270
+ req.on('end', () => {
271
+ try {
272
+ resolve(body ? JSON.parse(body) : {});
273
+ }
274
+ catch {
275
+ reject(new Error('Invalid JSON'));
276
+ }
277
+ });
278
+ req.on('error', reject);
279
+ });
280
+ };
281
+ // Helper to send JSON response
282
+ const sendJson = (res, status, data) => {
283
+ res.writeHead(status, { 'Content-Type': 'application/json' });
284
+ res.end(JSON.stringify(data));
285
+ };
286
+ // Notify webhooks of new message
287
+ const notifyWebhooks = async (message) => {
288
+ for (const url of webhooks) {
289
+ try {
290
+ await fetch(url, {
291
+ method: 'POST',
292
+ headers: { 'Content-Type': 'application/json' },
293
+ body: JSON.stringify(message),
294
+ });
295
+ }
296
+ catch (err) {
297
+ console.error(`[Webhook] Failed to notify ${url}:`, err);
298
+ }
299
+ }
300
+ };
301
+ // HTTP server with REST API
302
+ const server = createServer(async (req, res) => {
303
+ const url = new URL(req.url ?? '/', `http://localhost:${port}`);
304
+ const path = url.pathname;
305
+ const method = req.method ?? 'GET';
306
+ // CORS headers
307
+ res.setHeader('Access-Control-Allow-Origin', '*');
308
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
309
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
310
+ if (method === 'OPTIONS') {
311
+ res.writeHead(204);
312
+ res.end();
313
+ return;
314
+ }
315
+ try {
316
+ // REST API endpoints
317
+ if (path === '/api/status' && method === 'GET') {
318
+ sendJson(res, 200, {
319
+ connected: true,
320
+ peerID: client.peerID.toHex(),
321
+ nickname: client.nickname,
322
+ fingerprint: client.fingerprint,
323
+ peersCount: client.getConnectedPeers().length,
324
+ });
325
+ return;
326
+ }
327
+ if (path === '/api/peers' && method === 'GET') {
328
+ const peers = client.getConnectedPeers().map((p) => ({
329
+ peerID: p.peerID.toHex(),
330
+ nickname: p.nickname,
331
+ isConnected: p.isConnected,
332
+ lastSeen: Date.now(), // TODO: track actual last seen
333
+ }));
334
+ sendJson(res, 200, peers);
335
+ return;
336
+ }
337
+ if (path === '/api/messages' && method === 'GET') {
338
+ const since = parseInt(url.searchParams.get('since') ?? '0', 10);
339
+ const messages = messageStore.filter((m) => m.timestamp > since);
340
+ sendJson(res, 200, messages);
341
+ return;
342
+ }
343
+ if (path === '/api/send' && method === 'POST') {
344
+ const body = await parseBody(req);
345
+ const { type, text, recipientPeerID } = body;
346
+ if (!text || typeof text !== 'string') {
347
+ sendJson(res, 400, { error: 'Missing text field' });
348
+ return;
349
+ }
350
+ if (type === 'direct' && recipientPeerID) {
351
+ const { PeerID } = await import('../protocol/types.js');
352
+ await client.sendPrivateMessage(text, new PeerID(recipientPeerID));
353
+ }
354
+ else {
355
+ await client.sendPublicMessage(text);
356
+ }
357
+ sendJson(res, 200, { ok: true });
358
+ return;
359
+ }
360
+ if (path === '/api/webhook' && method === 'POST') {
361
+ const body = await parseBody(req);
362
+ const { url: webhookUrl } = body;
363
+ if (!webhookUrl || typeof webhookUrl !== 'string') {
364
+ sendJson(res, 400, { error: 'Missing url field' });
365
+ return;
366
+ }
367
+ if (!webhooks.includes(webhookUrl)) {
368
+ webhooks.push(webhookUrl);
369
+ }
370
+ sendJson(res, 200, { ok: true, registered: webhooks.length });
371
+ return;
372
+ }
373
+ if (path === '/api/webhook' && method === 'GET') {
374
+ sendJson(res, 200, { webhooks });
375
+ return;
376
+ }
377
+ // Web UI
378
+ if (path === '/' || path === '/index.html') {
379
+ res.writeHead(200, { 'Content-Type': 'text/html' });
380
+ res.end(HTML);
381
+ return;
382
+ }
383
+ res.writeHead(404);
384
+ res.end('Not found');
385
+ }
386
+ catch (err) {
387
+ console.error('[HTTP] Error:', err);
388
+ sendJson(res, 500, { error: err.message });
389
+ }
390
+ });
391
+ // WebSocket server
392
+ const wss = new WebSocketServer({ server, path: '/ws' });
393
+ wss.on('connection', (ws) => {
394
+ console.log('[WS] Client connected, total:', clients.size + 1);
395
+ clients.add(ws);
396
+ // Send init
397
+ ws.send(JSON.stringify({
398
+ type: 'init',
399
+ peerID: client.peerID.toHex(),
400
+ nickname: client.nickname,
401
+ fingerprint: client.fingerprint,
402
+ }));
403
+ // Send current peers
404
+ ws.send(JSON.stringify({
405
+ type: 'peers',
406
+ peers: client.getConnectedPeers().map((p) => ({
407
+ peerID: p.peerID.toHex(),
408
+ nickname: p.nickname,
409
+ isConnected: p.isConnected,
410
+ })),
411
+ }));
412
+ ws.on('message', async (data) => {
413
+ console.log('[WS] Received:', data.toString().slice(0, 100));
414
+ try {
415
+ const msg = JSON.parse(data.toString());
416
+ if (msg.type === 'send') {
417
+ console.log('[WS] Sending message:', msg.text, 'to:', msg.to || 'broadcast');
418
+ if (msg.to) {
419
+ // Private message
420
+ const { PeerID } = await import('../protocol/types.js');
421
+ await client.sendPrivateMessage(msg.text, new PeerID(msg.to));
422
+ }
423
+ else {
424
+ // Public message
425
+ await client.sendPublicMessage(msg.text);
426
+ }
427
+ console.log('[WS] Message sent successfully');
428
+ ws.send(JSON.stringify({ type: 'sent', text: msg.text }));
429
+ }
430
+ }
431
+ catch (error) {
432
+ console.error('[WS] Send error:', error.message);
433
+ ws.send(JSON.stringify({ type: 'error', error: error.message }));
434
+ }
435
+ });
436
+ ws.on('close', () => {
437
+ console.log('[WS] Client disconnected, remaining:', clients.size - 1);
438
+ clients.delete(ws);
439
+ });
440
+ });
441
+ // Forward client events to WebSocket clients
442
+ const broadcast = (msg) => {
443
+ const data = JSON.stringify(msg);
444
+ clients.forEach((ws) => {
445
+ if (ws.readyState === WebSocket.OPEN) {
446
+ ws.send(data);
447
+ }
448
+ });
449
+ };
450
+ client.on('message', (message) => {
451
+ // Store message for polling
452
+ const storedMessage = {
453
+ id: message.id,
454
+ type: message.isPrivate ? 'direct' : 'public',
455
+ senderPeerID: message.sender.toHex(),
456
+ senderNickname: message.senderNickname,
457
+ text: message.content,
458
+ timestamp: message.timestamp.getTime(),
459
+ };
460
+ messageStore.push(storedMessage);
461
+ if (messageStore.length > MAX_MESSAGES) {
462
+ messageStore.shift(); // Remove oldest
463
+ }
464
+ // Notify webhooks
465
+ notifyWebhooks(storedMessage).catch((err) => {
466
+ console.error('[Webhook] Notification error:', err);
467
+ });
468
+ // Broadcast to WebSocket clients
469
+ broadcast({
470
+ type: 'message',
471
+ message: {
472
+ id: message.id,
473
+ sender: message.sender.toHex(),
474
+ senderPeerID: message.sender.toHex(),
475
+ senderNickname: message.senderNickname,
476
+ content: message.content,
477
+ text: message.content,
478
+ timestamp: message.timestamp.toISOString(),
479
+ isPrivate: message.isPrivate,
480
+ isDirect: message.isPrivate,
481
+ },
482
+ });
483
+ });
484
+ client.on('peer:connected', (peer) => {
485
+ broadcast({
486
+ type: 'peer:connected',
487
+ peer: {
488
+ peerID: peer.peerID.toHex(),
489
+ nickname: peer.nickname,
490
+ isConnected: peer.isConnected,
491
+ },
492
+ });
493
+ });
494
+ client.on('peer:disconnected', (peerID) => {
495
+ broadcast({
496
+ type: 'peer:disconnected',
497
+ peerID: peerID.toHex(),
498
+ });
499
+ });
500
+ server.listen(port, () => {
501
+ console.log(`Bitchat UI: http://localhost:${port}`);
502
+ });
503
+ return {
504
+ stop: () => {
505
+ wss.close();
506
+ server.close();
507
+ },
508
+ };
509
+ }
510
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,79 @@
1
+ {
2
+ "name": "bitchat-node",
3
+ "version": "0.1.0",
4
+ "description": "Node.js implementation of the Bitchat BLE mesh protocol",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "bin": {
9
+ "bitchat": "./dist/bin/bitchat.js"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ },
16
+ "./protocol": {
17
+ "types": "./dist/protocol/index.d.ts",
18
+ "import": "./dist/protocol/index.js"
19
+ },
20
+ "./crypto": {
21
+ "types": "./dist/crypto/index.d.ts",
22
+ "import": "./dist/crypto/index.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "src",
28
+ "README.md"
29
+ ],
30
+ "scripts": {
31
+ "prepublishOnly": "npm run build",
32
+ "build": "tsc",
33
+ "dev": "tsc --watch",
34
+ "clean": "rm -rf dist",
35
+ "test": "vitest run",
36
+ "test:watch": "vitest",
37
+ "test:coverage": "vitest run --coverage",
38
+ "lint": "biome lint src/",
39
+ "lint:fix": "biome lint --write src/",
40
+ "format": "biome format --write src/",
41
+ "check": "biome check src/",
42
+ "check:fix": "biome check --write src/"
43
+ },
44
+ "dependencies": {
45
+ "@abandonware/bleno": "^0.6.2",
46
+ "@abandonware/noble": "^1.9.2-25",
47
+ "@stablelib/chacha20poly1305": "^1.0.1",
48
+ "@stablelib/ed25519": "^1.0.3",
49
+ "@stablelib/hmac": "^1.0.1",
50
+ "@stablelib/sha256": "^1.0.1",
51
+ "@stablelib/x25519": "^1.0.3",
52
+ "ws": "^8.16.0"
53
+ },
54
+ "devDependencies": {
55
+ "@biomejs/biome": "^2.3.14",
56
+ "@types/node": "^20.10.0",
57
+ "@types/ws": "^8.5.10",
58
+ "@vitest/coverage-v8": "^4.0.18",
59
+ "typescript": "^5.3.0",
60
+ "vitest": "^4.0.18"
61
+ },
62
+ "repository": {
63
+ "type": "git",
64
+ "url": "https://github.com/anthropics/bitchat-node"
65
+ },
66
+ "keywords": [
67
+ "bitchat",
68
+ "bluetooth",
69
+ "ble",
70
+ "mesh",
71
+ "noise-protocol",
72
+ "p2p",
73
+ "decentralized"
74
+ ],
75
+ "license": "Unlicense",
76
+ "engines": {
77
+ "node": ">=18"
78
+ }
79
+ }