sonic-ws 1.3.0-min → 1.3.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.
@@ -337,405 +337,404 @@ class SonicWSServer {
337
337
  data.password ??= "";
338
338
  if (data.port < 0 || data.port >= 65536)
339
339
  throw new Error("Port out of range!");
340
- /**
341
- * `
342
- <!DOCTYPE html>
343
- <html>
344
- <head>
345
- <meta charset="UTF-8">
346
- <script src="https://cdn.jsdelivr.net/gh/liwybloc/sonic-ws/bundled/SonicWS_bundle.js"></script>
347
- <title>SonicWS Debug Menu</title>
348
- <style>
349
- body {
350
- margin: 0;
351
- font-family: Inter, Arial, sans-serif;
352
- background: #0f1115;
353
- color: #e6e6e6;
354
- height: 100vh;
355
- display: flex;
356
- }
357
-
358
- #sidebar {
359
- width: 260px;
360
- background: #141821;
361
- border-right: 1px solid #1f2533;
362
- display: flex;
363
- flex-direction: column;
364
- }
365
-
366
- #sidebar-header {
367
- padding: 16px;
368
- font-weight: 600;
369
- font-size: 18px;
370
- border-bottom: 1px solid #1f2533;
371
- cursor: pointer;
372
- transition: color 0.2s;
373
- }
374
- #sidebar-header:hover {
375
- color: #dddddd;
376
- }
377
-
378
- #socket-list {
379
- flex: 1;
380
- overflow-y: auto;
381
- }
382
-
383
- .socket-item {
384
- padding: 10px 14px;
385
- cursor: pointer;
386
- border-bottom: 1px solid #1f2533;
387
- }
388
-
389
- .socket-item:hover {
390
- background: #1b2030;
391
- }
392
-
393
- .socket-item.active {
394
- background: #22294a;
395
- }
396
-
397
- .socket-id {
398
- font-size: 12px;
399
- opacity: 0.7;
400
- }
401
-
402
- #main {
403
- flex: 1;
404
- display: flex;
405
- flex-direction: column;
406
- }
407
-
408
- #main-header {
409
- padding: 17px;
410
- border-bottom: 1px solid #1f2533;
411
- display: flex;
412
- justify-content: space-between;
413
- align-items: center;
414
- }
415
-
416
- #stats {
417
- display: flex;
418
- gap: 20px;
419
- font-size: 13px;
420
- }
421
-
422
- #packets {
423
- flex: 1;
424
- overflow-y: auto;
425
- padding: 12px;
426
- }
427
-
428
- .packet {
429
- background: #1a1f2e;
430
- border-radius: 6px;
431
- padding: 6px 8px;
432
- margin-bottom: 4px;
433
- font-size: 12px;
434
- cursor: pointer;
435
- }
436
-
437
- .packet.sent { border-left: 3px solid #3cff7a; }
438
- .packet.recv { border-left: 3px solid #ff5a5a; }
439
-
440
- .packet-details {
441
- display: none;
442
- margin-top: 4px;
443
- opacity: 0.75;
444
- font-size: 11px;
445
- }
446
-
447
- .packet.expanded .packet-details {
448
- display: block;
449
- }
450
-
451
- button {
452
- background: none;
453
- }
454
- </style>
455
- </head>
456
- <body>
457
- <div id="sidebar">
458
- <div id="sidebar-header">Sonic WS Debug Menu</div>
459
- <div id="socket-list"></div>
460
- </div>
461
-
462
- <div id="main">
463
- <div id="main-header">
464
- <button id="close-socket" style="display:none;">❌</button>
465
- <div id="socket-title">Server Home</div>
466
- <div id="stats"></div>
467
- </div>
468
- <div id="home" style="display: block; padding: 16px;">
469
- <h2>Server Dashboard</h2>
470
- <div id="global-stats" style="margin-bottom:16px;"></div>
471
- <h3>Connection Logs</h3>
472
- <ul id="connection-logs" style="max-height:200px; overflow-y:auto; padding-left:16px;"></ul>
473
- <div style="margin-top:16px;">
474
- <table style="width:100%; border-collapse:collapse;">
475
- <thead>
476
- <tr>
477
- <th style="border-bottom:1px solid #444; text-align:left;">Socket ID</th>
478
- <th style="border-bottom:1px solid #444; text-align:left;">Name</th>
479
- <th style="border-bottom:1px solid #444; text-align:left;">Status</th>
480
- </tr>
481
- </thead>
482
- <tbody id="connection-table"></tbody>
483
- </table>
484
- </div>
485
- </div>
486
- <div id="packets"></div>
340
+ // there's no `` inside of it because i wanna use lib-htnml or whatever to make it hihglihted
341
+ const server = http_1.default.createServer((req, res) => {
342
+ res.writeHead(200, { 'Content-Type': 'text/html' });
343
+ const html = String.raw;
344
+ res.end(`
345
+ <!DOCTYPE html>
346
+ <html>
347
+ <head>
348
+ <meta charset="UTF-8">
349
+ <script src="https://cdn.jsdelivr.net/gh/liwybloc/sonic-ws/bundled/SonicWS_bundle.js"></script>
350
+ <title>SonicWS Debug Menu</title>
351
+ <style>
352
+ body {
353
+ margin: 0;
354
+ font-family: Inter, Arial, sans-serif;
355
+ background: #0f1115;
356
+ color: #e6e6e6;
357
+ height: 100vh;
358
+ display: flex;
359
+ }
360
+
361
+ #sidebar {
362
+ width: 260px;
363
+ background: #141821;
364
+ border-right: 1px solid #1f2533;
365
+ display: flex;
366
+ flex-direction: column;
367
+ }
368
+
369
+ #sidebar-header {
370
+ padding: 16px;
371
+ font-weight: 600;
372
+ font-size: 18px;
373
+ border-bottom: 1px solid #1f2533;
374
+ cursor: pointer;
375
+ transition: color 0.2s;
376
+ }
377
+ #sidebar-header:hover {
378
+ color: #dddddd;
379
+ }
380
+
381
+ #socket-list {
382
+ flex: 1;
383
+ overflow-y: auto;
384
+ }
385
+
386
+ .socket-item {
387
+ padding: 10px 14px;
388
+ cursor: pointer;
389
+ border-bottom: 1px solid #1f2533;
390
+ }
391
+
392
+ .socket-item:hover {
393
+ background: #1b2030;
394
+ }
395
+
396
+ .socket-item.active {
397
+ background: #22294a;
398
+ }
399
+
400
+ .socket-id {
401
+ font-size: 12px;
402
+ opacity: 0.7;
403
+ }
404
+
405
+ #main {
406
+ flex: 1;
407
+ display: flex;
408
+ flex-direction: column;
409
+ }
410
+
411
+ #main-header {
412
+ padding: 17px;
413
+ border-bottom: 1px solid #1f2533;
414
+ display: flex;
415
+ justify-content: space-between;
416
+ align-items: center;
417
+ }
418
+
419
+ #stats {
420
+ display: flex;
421
+ gap: 20px;
422
+ font-size: 13px;
423
+ }
424
+
425
+ #packets {
426
+ flex: 1;
427
+ overflow-y: auto;
428
+ padding: 12px;
429
+ }
430
+
431
+ .packet {
432
+ background: #1a1f2e;
433
+ border-radius: 6px;
434
+ padding: 6px 8px;
435
+ margin-bottom: 4px;
436
+ font-size: 12px;
437
+ cursor: pointer;
438
+ }
439
+
440
+ .packet.sent { border-left: 3px solid #3cff7a; }
441
+ .packet.recv { border-left: 3px solid #ff5a5a; }
442
+
443
+ .packet-details {
444
+ display: none;
445
+ margin-top: 4px;
446
+ opacity: 0.75;
447
+ font-size: 11px;
448
+ }
449
+
450
+ .packet.expanded .packet-details {
451
+ display: block;
452
+ }
453
+
454
+ button {
455
+ background: none;
456
+ }
457
+ </style>
458
+ </head>
459
+ <body>
460
+ <div id="sidebar">
461
+ <div id="sidebar-header">Sonic WS Debug Menu</div>
462
+ <div id="socket-list"></div>
463
+ </div>
464
+
465
+ <div id="main">
466
+ <div id="main-header">
467
+ <button id="close-socket" style="display:none;">❌</button>
468
+ <div id="socket-title">Server Home</div>
469
+ <div id="stats"></div>
470
+ </div>
471
+ <div id="home" style="display: block; padding: 16px;">
472
+ <h2>Server Dashboard</h2>
473
+ <div id="global-stats" style="margin-bottom:16px;"></div>
474
+ <h3>Connection Logs</h3>
475
+ <ul id="connection-logs" style="max-height:200px; overflow-y:auto; padding-left:16px;"></ul>
476
+ <div style="margin-top:16px;">
477
+ <table style="width:100%; border-collapse:collapse;">
478
+ <thead>
479
+ <tr>
480
+ <th style="border-bottom:1px solid #444; text-align:left;">Socket ID</th>
481
+ <th style="border-bottom:1px solid #444; text-align:left;">Name</th>
482
+ <th style="border-bottom:1px solid #444; text-align:left;">Status</th>
483
+ </tr>
484
+ </thead>
485
+ <tbody id="connection-table"></tbody>
486
+ </table>
487
487
  </div>
488
-
489
- <script>
490
- const socketList = document.getElementById('socket-list');
491
- const packetsDiv = document.getElementById('packets');
492
- const socketTitle = document.getElementById('socket-title');
493
- const debugTitle = document.getElementById('sidebar-header');
494
- const statsDiv = document.getElementById('stats');
495
- const home = document.getElementById('home');
496
- const closeSocketBtn = document.getElementById('close-socket');
497
-
498
- debugTitle.onclick = () => {
499
- if(activeId !== null) {
500
- activeId = null;
501
- packetsDiv.style.display = 'none';
502
- home.style.display = 'block';
503
- closeSocketBtn.style.display = 'none';
504
- renderGlobalStats();
505
- }
506
- };
507
-
508
- const globalStats = {
509
- totalSockets: 0,
510
- totalSent: 0,
511
- totalRecv: 0,
512
- totalSentBytes: 0,
513
- totalRecvBytes: 0,
514
- totalSaved: 0,
515
- startTime: 0,
516
- };
517
-
518
- function formatMilliseconds(ms) {
519
- if (ms < 1) return '0.0s';
520
-
521
- const units = [
522
- { label: 'week', value: 7 * 24 * 60 * 60 * 1000 },
523
- { label: 'day', value: 24 * 60 * 60 * 1000 },
524
- { label: 'hour', value: 60 * 60 * 1000 },
525
- { label: 'minute', value: 60 * 1000 },
526
- ];
527
-
528
- const parts = [];
529
-
530
- for (const { label, value } of units) {
531
- const amount = Math.floor(ms / value);
532
- if (amount > 0) {
533
- parts.push(amount + ' ' + label + (amount !== 1 ? 's' : ''));
534
- ms -= amount * value;
535
- }
536
- }
537
-
538
- if (ms > 0 || parts.length === 0) {
539
- const seconds = (ms / 1000).toFixed(1);
540
- parts.push(seconds + 's');
541
- }
542
-
543
- if (parts.length === 1) return parts[0];
544
- const last = parts.pop();
545
- return parts.join(', ') + ' and ' + last;
546
- }
547
-
548
-
549
- const globalStatsDiv = document.getElementById('global-stats');
550
- function renderGlobalStats() {
551
- const stats = globalStats;
552
- const uptime = Date.now() - stats.startTime;
553
- const formattedUptime = formatMilliseconds(uptime);
554
-
555
- globalStatsDiv.innerHTML = '<div><strong>Total Sockets:</strong> ' + stats.totalSockets + '</div><div><strong>Total Sent Packets:</strong> ' + stats.totalSent + '</div><div><strong>Total Received Packets:</strong> ' + stats.totalRecv + '</div><div><strong>Total Sent Bytes:</strong> ' + stats.totalSentBytes + ' B</div><div><strong>Total Received Bytes:</strong> ' + stats.totalRecvBytes + ' B</div><div><strong>Total Bandwidth Saved:</strong> ' + stats.totalSaved + ' B</div><div><strong>Uptime:</strong> ' + formattedUptime + '</div>';
556
- }
557
- setInterval(renderGlobalStats, 50);
558
-
559
- function updateConnectionTable() {
560
- const tbody = document.getElementById('connection-table');
561
- tbody.innerHTML = '';
562
- sockets.forEach(s => {
563
- const row = document.createElement('tr');
564
- row.innerHTML = '<td>' + s.id + '</td><td>' + s.name + '</td><td style="color:' + (s.el.style.color || '#0f0') + '">' + (s.el.style.color === '#f00' ? 'Disconnected' : 'Connected') + '</td>';
565
- tbody.appendChild(row);
566
- });
567
- }
568
- setInterval(updateConnectionTable, 1000);
569
-
570
- const sockets = new Map();
571
- let activeId = null;
572
-
573
- function selectSocket(id) {
574
- activeId = id;
575
- [...socketList.children].forEach(e => e.classList.toggle('active', e.dataset.id == id));
576
-
577
- const s = sockets.get(id);
578
- socketTitle.textContent = s.name;
579
- packetsDiv.innerHTML = '';
580
- s.packets.forEach(p => packetsDiv.appendChild(p.el));
581
- renderStats(s);
582
- home.style.display = 'none';
583
- packetsDiv.style.display = 'block';
584
- closeSocketBtn.style.display = 'block';
585
- }
586
-
587
- closeSocketBtn.onclick = () => {
588
- if(activeId === null) return;
589
- ws.send("close", Number(activeId));
590
- }
591
-
592
- function renderStats(s) {
593
- statsDiv.innerHTML = "<div>Sent: " + s.sent + "</div><div>Recv: " + s.recv + "</div><div>Sent bytes: " + s.sentBytes + "</div><div>Recv bytes: " + s.recvBytes + "</div><div>Saved: " + s.saved + "</div>";
594
- }
595
-
596
- function addSocket(id, name) {
597
- const el = document.createElement('div');
598
- el.className = 'socket-item';
599
- el.dataset.id = id;
600
- el.innerHTML = "<div>" + name + "</div><div class=\\"socket-id\\">#" + id + "</div>";
601
- el.onclick = () => selectSocket(id);
602
- socketList.appendChild(el);
603
-
604
- sockets.set(id, {
605
- id,
606
- name,
607
- el,
608
- packets: [],
609
- sent: 0,
610
- recv: 0,
611
- sentBytes: 0,
612
- recvBytes: 0,
613
- saved: 0
614
- });
615
- }
616
-
617
- function removeSocket(id, code, reason, codeReason) {
618
- const s = sockets.get(id);
619
- if (!s) return console.error("Unknown socket!!", id);
620
-
621
- s.el.dataset.id = id + "-closed";
622
- s.el.onclick = () => selectSocket(id + "-closed");
623
- sockets.set(id + "-closed", s);
624
- sockets.delete(id);
625
-
626
- if(activeId == id) activeId = id + "-closed";
627
-
628
- const nameNode = s.el.childNodes[0];
629
- nameNode.style.color = "#f00";
630
-
631
- let circle = document.createElement('span');
632
- circle.style.display = 'inline-block';
633
- circle.style.width = '10px';
634
- circle.style.height = '10px';
635
- circle.style.borderRadius = '50%';
636
- circle.style.background = '#ff5a5a';
637
- circle.style.marginLeft = '8px';
638
- nameNode.appendChild(circle);
639
-
640
- // add disconnection info to home page logs
641
- const logItem = document.createElement('li');
642
- logItem.textContent = 'Socket #' + id + ' disconnected — Code: ' + code + ', Reason: ' + reason + ', Closure Cause: ' + codeReason;
643
- document.getElementById('connection-logs').appendChild(logItem);
644
-
645
- requestAnimationFrame(() => circle.style.width = '100%');
646
- setTimeout(() => {
647
- circle.remove();
648
- s.el.remove();
649
- if(activeId == id + "-closed") {
650
- packetsDiv.style.display = 'none';
651
- home.style.display = 'block';
652
- closeSocketBtn.style.display = 'none';
653
- }
654
- }, 30000);
655
- }
656
-
657
- function addPacket(id, dir, tag, rawSize, saved, info, date, processTime) {
658
- const s = sockets.get(id);
659
- if (!s) return console.error("Unknown socket!!", id);
660
-
661
- const el = document.createElement('div');
662
- el.className = 'packet ' + (dir === 'sent' ? 'sent' : 'recv');
663
- el.innerHTML = '<div>' + tag + (info !== "undefined" ? ' — ' + info : '') + '</div><div class="packet-details">Raw Bytes: ' + rawSize + 'b (saved: ~' + saved + 'b)<br>Processed At: ' + new Date(date).toISOString() + '<br>Processing Time: ' + processTime.toFixed(2) + 'ms</div>';
664
-
665
- el.onclick = () => el.classList.toggle('expanded');
666
-
667
- s.packets.push({ el });
668
- if (dir === 'sent') {
669
- s.sent++;
670
- s.sentBytes += rawSize;
671
- } else {
672
- s.recv++;
673
- s.recvBytes += rawSize;
674
- }
675
- s.saved += saved;
676
-
677
- if (activeId === id) {
678
- packetsDiv.appendChild(el);
679
- renderStats(s);
680
- }
488
+ </div>
489
+ <div id="packets"></div>
490
+ </div>
491
+
492
+ <script>
493
+ const socketList = document.getElementById('socket-list');
494
+ const packetsDiv = document.getElementById('packets');
495
+ const socketTitle = document.getElementById('socket-title');
496
+ const debugTitle = document.getElementById('sidebar-header');
497
+ const statsDiv = document.getElementById('stats');
498
+ const home = document.getElementById('home');
499
+ const closeSocketBtn = document.getElementById('close-socket');
500
+
501
+ debugTitle.onclick = () => {
502
+ if(activeId !== null) {
503
+ activeId = null;
504
+ packetsDiv.style.display = 'none';
505
+ home.style.display = 'block';
506
+ closeSocketBtn.style.display = 'none';
507
+ renderGlobalStats();
508
+ }
509
+ };
510
+
511
+ const globalStats = {
512
+ totalSockets: 0,
513
+ totalSent: 0,
514
+ totalRecv: 0,
515
+ totalSentBytes: 0,
516
+ totalRecvBytes: 0,
517
+ totalSaved: 0,
518
+ startTime: 0,
519
+ };
520
+
521
+ function formatMilliseconds(ms) {
522
+ if (ms < 1) return '0.0s';
523
+
524
+ const units = [
525
+ { label: 'week', value: 7 * 24 * 60 * 60 * 1000 },
526
+ { label: 'day', value: 24 * 60 * 60 * 1000 },
527
+ { label: 'hour', value: 60 * 60 * 1000 },
528
+ { label: 'minute', value: 60 * 1000 },
529
+ ];
530
+
531
+ const parts = [];
532
+
533
+ for (const { label, value } of units) {
534
+ const amount = Math.floor(ms / value);
535
+ if (amount > 0) {
536
+ parts.push(amount + ' ' + label + (amount !== 1 ? 's' : ''));
537
+ ms -= amount * value;
681
538
  }
682
-
683
- function setStat(i, v) {
684
- globalStats[Object.keys(globalStats)[i]] = v;
685
- if (activeId === null) renderGlobalStats();
539
+ }
540
+
541
+ if (ms > 0 || parts.length === 0) {
542
+ const seconds = (ms / 1000).toFixed(1);
543
+ parts.push(seconds + 's');
544
+ }
545
+
546
+ if (parts.length === 1) return parts[0];
547
+ const last = parts.pop();
548
+ return parts.join(', ') + ' and ' + last;
549
+ }
550
+
551
+
552
+ const globalStatsDiv = document.getElementById('global-stats');
553
+ function renderGlobalStats() {
554
+ const stats = globalStats;
555
+ const uptime = Date.now() - stats.startTime;
556
+ const formattedUptime = formatMilliseconds(uptime);
557
+
558
+ globalStatsDiv.innerHTML = '<div><strong>Total Sockets:</strong> ' + stats.totalSockets + '</div><div><strong>Total Sent Packets:</strong> ' + stats.totalSent + '</div><div><strong>Total Received Packets:</strong> ' + stats.totalRecv + '</div><div><strong>Total Sent Bytes:</strong> ' + stats.totalSentBytes + ' B</div><div><strong>Total Received Bytes:</strong> ' + stats.totalRecvBytes + ' B</div><div><strong>Total Bandwidth Saved:</strong> ' + stats.totalSaved + ' B</div><div><strong>Uptime:</strong> ' + formattedUptime + '</div>';
559
+ }
560
+ setInterval(renderGlobalStats, 50);
561
+
562
+ function updateConnectionTable() {
563
+ const tbody = document.getElementById('connection-table');
564
+ tbody.innerHTML = '';
565
+ sockets.forEach(s => {
566
+ const row = document.createElement('tr');
567
+ row.innerHTML = '<td>' + s.id + '</td><td>' + s.name + '</td><td style="color:' + (s.el.style.color || '#0f0') + '">' + (s.el.style.color === '#f00' ? 'Disconnected' : 'Connected') + '</td>';
568
+ tbody.appendChild(row);
569
+ });
570
+ }
571
+ setInterval(updateConnectionTable, 1000);
572
+
573
+ const sockets = new Map();
574
+ let activeId = null;
575
+
576
+ function selectSocket(id) {
577
+ activeId = id;
578
+ [...socketList.children].forEach(e => e.classList.toggle('active', e.dataset.id == id));
579
+
580
+ const s = sockets.get(id);
581
+ socketTitle.textContent = s.name;
582
+ packetsDiv.innerHTML = '';
583
+ s.packets.forEach(p => packetsDiv.appendChild(p.el));
584
+ renderStats(s);
585
+ home.style.display = 'none';
586
+ packetsDiv.style.display = 'block';
587
+ closeSocketBtn.style.display = 'block';
588
+ }
589
+
590
+ closeSocketBtn.onclick = () => {
591
+ if(activeId === null) return;
592
+ ws.send("close", Number(activeId));
593
+ }
594
+
595
+ function renderStats(s) {
596
+ statsDiv.innerHTML = "<div>Sent: " + s.sent + "</div><div>Recv: " + s.recv + "</div><div>Sent bytes: " + s.sentBytes + "</div><div>Recv bytes: " + s.recvBytes + "</div><div>Saved: " + s.saved + "</div>";
597
+ }
598
+
599
+ function addSocket(id, name) {
600
+ const el = document.createElement('div');
601
+ el.className = 'socket-item';
602
+ el.dataset.id = id;
603
+ el.innerHTML = "<div>" + name + "</div><div class=\\"socket-id\\">#" + id + "</div>";
604
+ el.onclick = () => selectSocket(id);
605
+ socketList.appendChild(el);
606
+
607
+ sockets.set(id, {
608
+ id,
609
+ name,
610
+ el,
611
+ packets: [],
612
+ sent: 0,
613
+ recv: 0,
614
+ sentBytes: 0,
615
+ recvBytes: 0,
616
+ saved: 0
617
+ });
618
+ }
619
+
620
+ function removeSocket(id, code, reason, codeReason) {
621
+ const s = sockets.get(id);
622
+ if (!s) return console.error("Unknown socket!!", id);
623
+
624
+ s.el.dataset.id = id + "-closed";
625
+ s.el.onclick = () => selectSocket(id + "-closed");
626
+ sockets.set(id + "-closed", s);
627
+ sockets.delete(id);
628
+
629
+ if(activeId == id) activeId = id + "-closed";
630
+
631
+ const nameNode = s.el.childNodes[0];
632
+ nameNode.style.color = "#f00";
633
+
634
+ let circle = document.createElement('span');
635
+ circle.style.display = 'inline-block';
636
+ circle.style.width = '10px';
637
+ circle.style.height = '10px';
638
+ circle.style.borderRadius = '50%';
639
+ circle.style.background = '#ff5a5a';
640
+ circle.style.marginLeft = '8px';
641
+ nameNode.appendChild(circle);
642
+
643
+ // add disconnection info to home page logs
644
+ const logItem = document.createElement('li');
645
+ logItem.textContent = 'Socket #' + id + ' disconnected — Code: ' + code + ', Reason: ' + reason + ', Closure Cause: ' + codeReason;
646
+ document.getElementById('connection-logs').appendChild(logItem);
647
+
648
+ requestAnimationFrame(() => circle.style.width = '100%');
649
+ setTimeout(() => {
650
+ circle.remove();
651
+ s.el.remove();
652
+ if(activeId == id + "-closed") {
653
+ packetsDiv.style.display = 'none';
654
+ home.style.display = 'block';
655
+ closeSocketBtn.style.display = 'none';
686
656
  }
687
-
688
- const ws = new SonicWS('ws://' + location.host);
689
-
690
- ws.on("connection", id => addSocket(id, "Socket " + id));
691
- ws.on("disconnection", ([id, code], [reason, codeReason]) => removeSocket(id, code, reason, codeReason));
692
- ws.on("nameChange", ([id], [name]) => {
693
- const s = sockets.get(id);
694
- if (!s) return console.error("Unknown socket!!", id);
695
- s.name = name;
696
- s.el.firstChild.textContent = name;
697
- if (activeId === id) socketTitle.textContent = name;
698
- });
699
- ws.on("packet", ([id, size, saved], [dir], [tag], [values], [time, processTime]) => {
700
- console.log("Received packet", { id, size, saved, dir, tag, values, time, processTime });
701
- addPacket(id, dir, tag, size, saved, values, time, processTime);
702
- });
703
- ws.on("stats", (stats) => {
704
- console.log("Received stats", stats);
705
- stats.forEach((v, i) => setStat(i, v));
706
- });
707
- ws.on("stat", (i, v) => setStat(i, v));
708
-
709
- const lastKnownPassword = localStorage.getItem("password");
710
- const empty = !localStorage.getItem("req");
711
- let usedPass = "";
712
- ws.on_ready(() => {
713
- if(empty) ws.send("password", "");
714
- else ws.send("password", usedPass = (lastKnownPassword ?? prompt("Please enter password")));
715
- });
716
-
717
- ws.on_close(() => {
718
- localStorage.setItem("req", true);
719
- localStorage.removeItem("password");
720
- setTimeout(() => window.location.reload(), 1000);
721
- });
722
-
723
- ws.on("authenticated", (success) => {
724
- console.log("Auth status:", success);
725
- if(!success) {
726
- } else {
727
- localStorage.setItem("req", usedPass.length > 0);
728
- localStorage.setItem("password", usedPass);
729
- }
730
- })
731
- </script>
732
- </body>
733
- </html>
734
- `
735
- */
736
- const server = http_1.default.createServer((req, res) => {
737
- res.writeHead(200, { 'Content-Type': 'text/html' });
738
- res.end(`<!doctypehtml><meta charset=UTF-8><script src=https://cdn.jsdelivr.net/gh/liwybloc/sonic-ws/bundled/SonicWS_bundle.js></script><title>SonicWS Debug Menu</title><style>body{margin:0;font-family:Inter,Arial,sans-serif;background:#0f1115;color:#e6e6e6;height:100vh;display:flex}#sidebar{width:260px;background:#141821;border-right:1px solid #1f2533;display:flex;flex-direction:column}#sidebar-header{padding:16px;font-weight:600;font-size:18px;border-bottom:1px solid #1f2533;cursor:pointer;transition:color .2s}#sidebar-header:hover{color:#ddd}#socket-list{flex:1;overflow-y:auto}.socket-item{padding:10px 14px;cursor:pointer;border-bottom:1px solid #1f2533}.socket-item:hover{background:#1b2030}.socket-item.active{background:#22294a}.socket-id{font-size:12px;opacity:.7}#main{flex:1;display:flex;flex-direction:column}#main-header{padding:17px;border-bottom:1px solid #1f2533;display:flex;justify-content:space-between;align-items:center}#stats{display:flex;gap:20px;font-size:13px}#packets{flex:1;overflow-y:auto;padding:12px}.packet{background:#1a1f2e;border-radius:6px;padding:6px 8px;margin-bottom:4px;font-size:12px;cursor:pointer}.packet.sent{border-left:3px solid #3cff7a}.packet.recv{border-left:3px solid #ff5a5a}.packet-details{display:none;margin-top:4px;opacity:.75;font-size:11px}.packet.expanded .packet-details{display:block}button{background:0 0}</style><div id=sidebar><div id=sidebar-header>Sonic WS Debug Menu</div><div id=socket-list></div></div><div id=main><div id=main-header><button id=close-socket style=display:none>❌</button><div id=socket-title>Server Home</div><div id=stats></div></div><div id=home style=display:block;padding:16px><h2>Server Dashboard</h2><div id=global-stats style=margin-bottom:16px></div><h3>Connection Logs</h3><ul id=connection-logs style=max-height:200px;overflow-y:auto;padding-left:16px></ul><div style=margin-top:16px><table style=width:100%;border-collapse:collapse><thead><tr><th style="border-bottom:1px solid #444;text-align:left">Socket ID<th style="border-bottom:1px solid #444;text-align:left">Name<th style="border-bottom:1px solid #444;text-align:left">Status<tbody id=connection-table></table></div></div><div id=packets></div></div><script>const socketList=document.getElementById("socket-list"),packetsDiv=document.getElementById("packets"),socketTitle=document.getElementById("socket-title"),debugTitle=document.getElementById("sidebar-header"),statsDiv=document.getElementById("stats"),home=document.getElementById("home"),closeSocketBtn=document.getElementById("close-socket");debugTitle.onclick=()=>{null!==activeId&&(activeId=null,packetsDiv.style.display="none",home.style.display="block",closeSocketBtn.style.display="none",renderGlobalStats())};const globalStats={totalSockets:0,totalSent:0,totalRecv:0,totalSentBytes:0,totalRecvBytes:0,totalSaved:0,startTime:0};function formatMilliseconds(e){if(e<1)return"0.0s";const t=[{label:"week",value:6048e5},{label:"day",value:864e5},{label:"hour",value:36e5},{label:"minute",value:6e4}],s=[];for(const{label:o,value:n}of t){const t=Math.floor(e/n);t>0&&(s.push(t+" "+o+(1!==t?"s":"")),e-=t*n)}if(e>0||0===s.length){const t=(e/1e3).toFixed(1);s.push(t+"s")}if(1===s.length)return s[0];const o=s.pop();return s.join(", ")+" and "+o}const globalStatsDiv=document.getElementById("global-stats");function renderGlobalStats(){const e=globalStats,t=formatMilliseconds(Date.now()-e.startTime);globalStatsDiv.innerHTML="<div><strong>Total Sockets:</strong> "+e.totalSockets+"</div><div><strong>Total Sent Packets:</strong> "+e.totalSent+"</div><div><strong>Total Received Packets:</strong> "+e.totalRecv+"</div><div><strong>Total Sent Bytes:</strong> "+e.totalSentBytes+" B</div><div><strong>Total Received Bytes:</strong> "+e.totalRecvBytes+" B</div><div><strong>Total Bandwidth Saved:</strong> "+e.totalSaved+" B</div><div><strong>Uptime:</strong> "+t+"</div>"}function updateConnectionTable(){const e=document.getElementById("connection-table");e.innerHTML="",sockets.forEach((t=>{const s=document.createElement("tr");s.innerHTML="<td>"+t.id+"</td><td>"+t.name+'</td><td style="color:'+(t.el.style.color||"#0f0")+'">'+("#f00"===t.el.style.color?"Disconnected":"Connected")+"</td>",e.appendChild(s)}))}setInterval(renderGlobalStats,50),setInterval(updateConnectionTable,1e3);const sockets=new Map;let activeId=null;function selectSocket(e){activeId=e,[...socketList.children].forEach((t=>t.classList.toggle("active",t.dataset.id==e)));const t=sockets.get(e);socketTitle.textContent=t.name,packetsDiv.innerHTML="",t.packets.forEach((e=>packetsDiv.appendChild(e.el))),renderStats(t),home.style.display="none",packetsDiv.style.display="block",closeSocketBtn.style.display="block"}function renderStats(e){statsDiv.innerHTML="<div>Sent: "+e.sent+"</div><div>Recv: "+e.recv+"</div><div>Sent bytes: "+e.sentBytes+"</div><div>Recv bytes: "+e.recvBytes+"</div><div>Saved: "+e.saved+"</div>"}function addSocket(e,t){const s=document.createElement("div");s.className="socket-item",s.dataset.id=e,s.innerHTML="<div>"+t+'</div><div class="socket-id">#'+e+"</div>",s.onclick=()=>selectSocket(e),socketList.appendChild(s),sockets.set(e,{id:e,name:t,el:s,packets:[],sent:0,recv:0,sentBytes:0,recvBytes:0,saved:0})}function removeSocket(e,t,s,o){const n=sockets.get(e);if(!n)return console.error("Unknown socket!!",e);n.el.dataset.id=e+"-closed",n.el.onclick=()=>selectSocket(e+"-closed"),sockets.set(e+"-closed",n),sockets.delete(e),activeId==e&&(activeId=e+"-closed");const c=n.el.childNodes[0];c.style.color="#f00";let l=document.createElement("span");l.style.display="inline-block",l.style.width="10px",l.style.height="10px",l.style.borderRadius="50%",l.style.background="#ff5a5a",l.style.marginLeft="8px",c.appendChild(l);const a=document.createElement("li");a.textContent="Socket #"+e+" disconnected — Code: "+t+", Reason: "+s+", Closure Cause: "+o,document.getElementById("connection-logs").appendChild(a),requestAnimationFrame((()=>l.style.width="100%")),setTimeout((()=>{l.remove(),n.el.remove(),activeId==e+"-closed"&&(packetsDiv.style.display="none",home.style.display="block",closeSocketBtn.style.display="none")}),3e4)}function addPacket(e,t,s,o,n,c,l,a){const d=sockets.get(e);if(!d)return console.error("Unknown socket!!",e);const i=document.createElement("div");i.className="packet "+("sent"===t?"sent":"recv"),i.innerHTML="<div>"+s+("undefined"!==c?" — "+c:"")+'</div><div class="packet-details">Raw Bytes: '+o+"b (saved: ~"+n+"b)<br>Processed At: "+new Date(l).toISOString()+"<br>Processing Time: "+a.toFixed(2)+"ms</div>",i.onclick=()=>i.classList.toggle("expanded"),d.packets.push({el:i}),"sent"===t?(d.sent++,d.sentBytes+=o):(d.recv++,d.recvBytes+=o),d.saved+=n,activeId===e&&(packetsDiv.appendChild(i),renderStats(d))}function setStat(e,t){globalStats[Object.keys(globalStats)[e]]=t,null===activeId&&renderGlobalStats()}closeSocketBtn.onclick=()=>{null!==activeId&&ws.send("close",Number(activeId))};const ws=new SonicWS("ws://"+location.host);ws.on("connection",(e=>addSocket(e,"Socket "+e))),ws.on("disconnection",(([e,t],[s,o])=>removeSocket(e,t,s,o))),ws.on("nameChange",(([e],[t])=>{const s=sockets.get(e);if(!s)return console.error("Unknown socket!!",e);s.name=t,s.el.firstChild.textContent=t,activeId===e&&(socketTitle.textContent=t)})),ws.on("packet",(([e,t,s],[o],[n],[c],[l,a])=>{console.log("Received packet",{id:e,size:t,saved:s,dir:o,tag:n,values:c,time:l,processTime:a}),addPacket(e,o,n,t,s,c,l,a)})),ws.on("stats",(e=>{console.log("Received stats",e),e.forEach(((e,t)=>setStat(t,e)))})),ws.on("stat",((e,t)=>setStat(e,t)));const lastKnownPassword=localStorage.getItem("password"),empty=!localStorage.getItem("req");let usedPass="";ws.on_ready((()=>{empty?ws.send("password",""):ws.send("password",usedPass=lastKnownPassword??prompt("Please enter password"))})),ws.on_close((()=>{localStorage.setItem("req",!0),localStorage.removeItem("password"),setTimeout((()=>window.location.reload()),1e3)})),ws.on("authenticated",(e=>{console.log("Auth status:",e),e&&(localStorage.setItem("req",usedPass.length>0),localStorage.setItem("password",usedPass))}));</script>`);
657
+ }, 30000);
658
+ }
659
+
660
+ function addPacket(id, dir, tag, rawSize, saved, info, date, processTime) {
661
+ const s = sockets.get(id);
662
+ if (!s) return console.error("Unknown socket!!", id);
663
+
664
+ const el = document.createElement('div');
665
+ el.className = 'packet ' + (dir === 'sent' ? 'sent' : 'recv');
666
+ el.innerHTML = '<div>' + tag + (info !== "undefined" ? ' — ' + info : '') + '</div><div class="packet-details">Raw Bytes: ' + rawSize + 'b (saved: ~' + saved + 'b)<br>Processed At: ' + new Date(date).toISOString() + '<br>Processing Time: ' + processTime.toFixed(2) + 'ms</div>';
667
+
668
+ el.onclick = () => el.classList.toggle('expanded');
669
+
670
+ s.packets.push({ el });
671
+ if (dir === 'sent') {
672
+ s.sent++;
673
+ s.sentBytes += rawSize;
674
+ } else {
675
+ s.recv++;
676
+ s.recvBytes += rawSize;
677
+ }
678
+ s.saved += saved;
679
+
680
+ if (activeId === id) {
681
+ packetsDiv.appendChild(el);
682
+ renderStats(s);
683
+ }
684
+ }
685
+
686
+ function setStat(i, v) {
687
+ globalStats[Object.keys(globalStats)[i]] = v;
688
+ if (activeId === null) renderGlobalStats();
689
+ }
690
+
691
+ const ws = new SonicWS('ws://' + location.host);
692
+
693
+ ws.on("connection", id => addSocket(id, "Socket " + id));
694
+ ws.on("disconnection", ([id, code], [reason, codeReason]) => removeSocket(id, code, reason, codeReason));
695
+ ws.on("nameChange", ([id], [name]) => {
696
+ const s = sockets.get(id);
697
+ if (!s) return console.error("Unknown socket!!", id);
698
+ s.name = name;
699
+ s.el.firstChild.textContent = name;
700
+ if (activeId === id) socketTitle.textContent = name;
701
+ });
702
+ ws.on("packet", ([id, size, saved], [dir], [tag], [values], [time, processTime]) => {
703
+ console.log("Received packet", { id, size, saved, dir, tag, values, time, processTime });
704
+ addPacket(id, dir, tag, size, saved, values, time, processTime);
705
+ });
706
+ ws.on("stats", (stats) => {
707
+ console.log("Received stats", stats);
708
+ stats.forEach((v, i) => setStat(i, v));
709
+ });
710
+ ws.on("stat", (i, v) => setStat(i, v));
711
+
712
+ const lastKnownPassword = localStorage.getItem("password");
713
+ const empty = !localStorage.getItem("req");
714
+ let usedPass = "";
715
+ ws.on_ready(() => {
716
+ if(empty) ws.send("password", "");
717
+ else ws.send("password", usedPass = (lastKnownPassword ?? prompt("Please enter password")));
718
+ });
719
+
720
+ ws.on_close(() => {
721
+ localStorage.setItem("req", true);
722
+ localStorage.removeItem("password");
723
+ setTimeout(() => window.location.reload(), 1000);
724
+ });
725
+
726
+ ws.on("authenticated", (success) => {
727
+ console.log("Auth status:", success);
728
+ if(!success) {
729
+ } else {
730
+ localStorage.setItem("req", usedPass.length > 0);
731
+ localStorage.setItem("password", usedPass);
732
+ }
733
+ })
734
+ </script>
735
+ </body>
736
+ </html>
737
+ `);
739
738
  });
740
739
  const wss = new SonicWSServer({
741
740
  clientPackets: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonic-ws",
3
- "version": "1.3.0-min",
3
+ "version": "1.3.0",
4
4
  "description": "Ultra-lightweight, high-performance, and bandwidth efficient websocket library",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",