react-native-ble-mesh 2.0.0 → 2.1.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.
Files changed (93) hide show
  1. package/README.md +2 -2
  2. package/docs/OPTIMIZATION.md +165 -52
  3. package/package.json +1 -1
  4. package/src/MeshNetwork.js +63 -53
  5. package/src/constants/audio.js +4 -4
  6. package/src/constants/ble.js +1 -1
  7. package/src/constants/crypto.js +1 -1
  8. package/src/constants/errors.js +2 -2
  9. package/src/constants/events.js +1 -1
  10. package/src/constants/protocol.js +2 -2
  11. package/src/crypto/AutoCrypto.js +16 -3
  12. package/src/crypto/CryptoProvider.js +17 -17
  13. package/src/crypto/providers/ExpoCryptoProvider.js +15 -9
  14. package/src/crypto/providers/QuickCryptoProvider.js +41 -12
  15. package/src/crypto/providers/TweetNaClProvider.js +10 -8
  16. package/src/errors/AudioError.js +2 -1
  17. package/src/errors/ConnectionError.js +2 -2
  18. package/src/errors/CryptoError.js +1 -1
  19. package/src/errors/HandshakeError.js +2 -2
  20. package/src/errors/MeshError.js +4 -4
  21. package/src/errors/MessageError.js +2 -2
  22. package/src/errors/ValidationError.js +3 -3
  23. package/src/expo/withBLEMesh.js +10 -10
  24. package/src/hooks/AppStateManager.js +11 -2
  25. package/src/hooks/useMesh.js +23 -10
  26. package/src/hooks/useMessages.js +17 -16
  27. package/src/hooks/usePeers.js +19 -14
  28. package/src/index.js +2 -2
  29. package/src/mesh/dedup/BloomFilter.js +45 -57
  30. package/src/mesh/dedup/DedupManager.js +36 -8
  31. package/src/mesh/dedup/MessageCache.js +3 -0
  32. package/src/mesh/fragment/Assembler.js +5 -4
  33. package/src/mesh/fragment/Fragmenter.js +3 -3
  34. package/src/mesh/monitor/ConnectionQuality.js +59 -25
  35. package/src/mesh/monitor/NetworkMonitor.js +80 -28
  36. package/src/mesh/peer/Peer.js +9 -11
  37. package/src/mesh/peer/PeerDiscovery.js +18 -19
  38. package/src/mesh/peer/PeerManager.js +29 -17
  39. package/src/mesh/router/MessageRouter.js +28 -20
  40. package/src/mesh/router/PathFinder.js +10 -13
  41. package/src/mesh/router/RouteTable.js +25 -14
  42. package/src/mesh/store/StoreAndForwardManager.js +32 -24
  43. package/src/protocol/deserializer.js +9 -10
  44. package/src/protocol/header.js +13 -7
  45. package/src/protocol/message.js +18 -14
  46. package/src/protocol/serializer.js +9 -12
  47. package/src/protocol/validator.js +29 -10
  48. package/src/service/BatteryOptimizer.js +22 -18
  49. package/src/service/EmergencyManager.js +18 -25
  50. package/src/service/HandshakeManager.js +112 -18
  51. package/src/service/MeshService.js +106 -22
  52. package/src/service/SessionManager.js +50 -13
  53. package/src/service/audio/AudioManager.js +80 -38
  54. package/src/service/audio/buffer/FrameBuffer.js +7 -8
  55. package/src/service/audio/buffer/JitterBuffer.js +1 -1
  56. package/src/service/audio/codec/LC3Codec.js +18 -19
  57. package/src/service/audio/codec/LC3Decoder.js +10 -10
  58. package/src/service/audio/codec/LC3Encoder.js +11 -9
  59. package/src/service/audio/session/AudioSession.js +14 -17
  60. package/src/service/audio/session/VoiceMessage.js +15 -22
  61. package/src/service/audio/transport/AudioFragmenter.js +17 -9
  62. package/src/service/audio/transport/AudioFramer.js +8 -12
  63. package/src/service/file/FileAssembler.js +4 -2
  64. package/src/service/file/FileChunker.js +1 -1
  65. package/src/service/file/FileManager.js +26 -20
  66. package/src/service/file/FileMessage.js +7 -12
  67. package/src/service/text/TextManager.js +75 -42
  68. package/src/service/text/broadcast/BroadcastManager.js +14 -17
  69. package/src/service/text/channel/Channel.js +10 -14
  70. package/src/service/text/channel/ChannelManager.js +10 -10
  71. package/src/service/text/message/TextMessage.js +12 -19
  72. package/src/service/text/message/TextSerializer.js +2 -2
  73. package/src/storage/AsyncStorageAdapter.js +17 -14
  74. package/src/storage/MemoryStorage.js +11 -8
  75. package/src/storage/MessageStore.js +77 -32
  76. package/src/storage/Storage.js +9 -9
  77. package/src/transport/BLETransport.js +27 -16
  78. package/src/transport/MockTransport.js +7 -2
  79. package/src/transport/MultiTransport.js +43 -11
  80. package/src/transport/Transport.js +9 -9
  81. package/src/transport/WiFiDirectTransport.js +26 -20
  82. package/src/transport/adapters/BLEAdapter.js +19 -19
  83. package/src/transport/adapters/NodeBLEAdapter.js +24 -23
  84. package/src/transport/adapters/RNBLEAdapter.js +14 -11
  85. package/src/utils/EventEmitter.js +15 -16
  86. package/src/utils/LRUCache.js +10 -4
  87. package/src/utils/RateLimiter.js +1 -1
  88. package/src/utils/bytes.js +12 -10
  89. package/src/utils/compression.js +10 -8
  90. package/src/utils/encoding.js +39 -8
  91. package/src/utils/retry.js +11 -13
  92. package/src/utils/time.js +9 -4
  93. package/src/utils/validation.js +1 -1
@@ -66,7 +66,7 @@ function createFragmentHeader(index, total, payloadLength) {
66
66
  /**
67
67
  * Parses a fragment header
68
68
  * @param {Uint8Array} data - Fragment data
69
- * @returns {Object} Parsed header { index, total, payloadLength }
69
+ * @returns {any} Parsed header { index, total, payloadLength }
70
70
  */
71
71
  function parseFragmentHeader(data) {
72
72
  if (data.length < FRAGMENT_HEADER_SIZE) {
@@ -121,7 +121,7 @@ function fragment(payload, messageId, maxSize = DEFAULT_FRAGMENT_SIZE) {
121
121
  for (let i = 0; i < fragmentCount; i++) {
122
122
  const remainingLength = payload.length - offset;
123
123
  const chunkLength = Math.min(payloadCapacity, remainingLength);
124
- const chunk = payload.slice(offset, offset + chunkLength);
124
+ const chunk = payload.subarray(offset, offset + chunkLength);
125
125
 
126
126
  // Create fragment with header
127
127
  const header = createFragmentHeader(i, fragmentCount, chunkLength);
@@ -139,7 +139,7 @@ function fragment(payload, messageId, maxSize = DEFAULT_FRAGMENT_SIZE) {
139
139
  /**
140
140
  * Gets fragment information without parsing full data
141
141
  * @param {Uint8Array} fragmentData - Fragment data
142
- * @returns {Object} Fragment info { index, total, payloadLength, payload }
142
+ * @returns {any} Fragment info { index, total, payloadLength, payload }
143
143
  */
144
144
  function getFragmentInfo(fragmentData) {
145
145
  const header = parseFragmentHeader(fragmentData);
@@ -12,7 +12,7 @@ const EventEmitter = require('../../utils/EventEmitter');
12
12
 
13
13
  /**
14
14
  * Connection quality levels
15
- * @constant {Object}
15
+ * @constant {any}
16
16
  */
17
17
  const QUALITY_LEVEL = Object.freeze({
18
18
  EXCELLENT: 'excellent',
@@ -24,7 +24,7 @@ const QUALITY_LEVEL = Object.freeze({
24
24
 
25
25
  /**
26
26
  * Default quality configuration
27
- * @constant {Object}
27
+ * @constant {any}
28
28
  */
29
29
  const DEFAULT_CONFIG = Object.freeze({
30
30
  /** How often to recalculate quality (ms) */
@@ -50,14 +50,28 @@ const DEFAULT_CONFIG = Object.freeze({
50
50
  * @class PeerQualityTracker
51
51
  */
52
52
  class PeerQualityTracker {
53
+ /**
54
+ * @param {string} peerId
55
+ * @param {any} config
56
+ */
53
57
  constructor(peerId, config) {
54
58
  this.peerId = peerId;
59
+ /** @type {any} */
55
60
  this._config = config;
56
- this._rssiSamples = [];
57
- this._latencySamples = [];
61
+ // Circular buffer for RSSI samples
62
+ this._rssiSamples = new Float64Array(config.sampleSize);
63
+ this._rssiIndex = 0;
64
+ this._rssiCount = 0;
65
+ this._rssiSum = 0;
66
+ // Circular buffer for latency samples
67
+ this._latencySamples = new Float64Array(config.sampleSize);
68
+ this._latencyIndex = 0;
69
+ this._latencyCount = 0;
70
+ this._latencySum = 0;
58
71
  this._packetsSent = 0;
59
72
  this._packetsAcked = 0;
60
73
  this._bytesTransferred = 0;
74
+ /** @type {number|null} */
61
75
  this._transferStartTime = null;
62
76
  this._lastActivity = Date.now();
63
77
  this._transport = 'ble';
@@ -65,25 +79,37 @@ class PeerQualityTracker {
65
79
  }
66
80
 
67
81
  /**
68
- * Records an RSSI sample
82
+ * Records an RSSI sample using circular buffer
69
83
  * @param {number} rssi - Signal strength in dBm
70
84
  */
71
85
  recordRssi(rssi) {
72
- this._rssiSamples.push(rssi);
73
- if (this._rssiSamples.length > this._config.sampleSize) {
74
- this._rssiSamples.shift();
86
+ const capacity = this._rssiSamples.length;
87
+ if (this._rssiCount >= capacity) {
88
+ this._rssiSum -= this._rssiSamples[this._rssiIndex];
89
+ }
90
+ this._rssiSamples[this._rssiIndex] = rssi;
91
+ this._rssiSum += rssi;
92
+ this._rssiIndex = (this._rssiIndex + 1) % capacity;
93
+ if (this._rssiCount < capacity) {
94
+ this._rssiCount++;
75
95
  }
76
96
  this._lastActivity = Date.now();
77
97
  }
78
98
 
79
99
  /**
80
- * Records a latency measurement
100
+ * Records a latency measurement using circular buffer
81
101
  * @param {number} latencyMs - Round-trip latency in ms
82
102
  */
83
103
  recordLatency(latencyMs) {
84
- this._latencySamples.push(latencyMs);
85
- if (this._latencySamples.length > this._config.sampleSize) {
86
- this._latencySamples.shift();
104
+ const capacity = this._latencySamples.length;
105
+ if (this._latencyCount >= capacity) {
106
+ this._latencySum -= this._latencySamples[this._latencyIndex];
107
+ }
108
+ this._latencySamples[this._latencyIndex] = latencyMs;
109
+ this._latencySum += latencyMs;
110
+ this._latencyIndex = (this._latencyIndex + 1) % capacity;
111
+ if (this._latencyCount < capacity) {
112
+ this._latencyCount++;
87
113
  }
88
114
  this._lastActivity = Date.now();
89
115
  }
@@ -125,21 +151,21 @@ class PeerQualityTracker {
125
151
  }
126
152
 
127
153
  /**
128
- * Gets the average RSSI
154
+ * Gets the average RSSI (O(1) using running sum)
129
155
  * @returns {number|null}
130
156
  */
131
157
  getAvgRssi() {
132
- if (this._rssiSamples.length === 0) { return null; }
133
- return this._rssiSamples.reduce((a, b) => a + b, 0) / this._rssiSamples.length;
158
+ if (this._rssiCount === 0) { return null; }
159
+ return this._rssiSum / this._rssiCount;
134
160
  }
135
161
 
136
162
  /**
137
- * Gets the average latency
163
+ * Gets the average latency (O(1) using running sum)
138
164
  * @returns {number|null}
139
165
  */
140
166
  getAvgLatency() {
141
- if (this._latencySamples.length === 0) { return null; }
142
- return this._latencySamples.reduce((a, b) => a + b, 0) / this._latencySamples.length;
167
+ if (this._latencyCount === 0) { return null; }
168
+ return this._latencySum / this._latencyCount;
143
169
  }
144
170
 
145
171
  /**
@@ -173,7 +199,7 @@ class PeerQualityTracker {
173
199
  /**
174
200
  * Calculates quality score (0-1) for a metric
175
201
  * @param {number|null} value - Metric value
176
- * @param {Object} thresholds - {excellent, good, fair}
202
+ * @param {any} thresholds - {excellent, good, fair}
177
203
  * @param {boolean} [higherIsBetter=false]
178
204
  * @returns {number}
179
205
  */
@@ -196,7 +222,7 @@ class PeerQualityTracker {
196
222
 
197
223
  /**
198
224
  * Calculates overall quality
199
- * @returns {Object} Quality report
225
+ * @returns {any} Quality report
200
226
  */
201
227
  calculate() {
202
228
  if (this.isTimedOut()) {
@@ -231,6 +257,7 @@ class PeerQualityTracker {
231
257
  if (score >= 0.8) { level = QUALITY_LEVEL.EXCELLENT; } else if (score >= 0.6) { level = QUALITY_LEVEL.GOOD; } else if (score >= 0.4) { level = QUALITY_LEVEL.FAIR; } else { level = QUALITY_LEVEL.POOR; }
232
258
 
233
259
  const previousLevel = this._currentLevel;
260
+ // @ts-ignore
234
261
  this._currentLevel = level;
235
262
 
236
263
  return {
@@ -255,13 +282,15 @@ class PeerQualityTracker {
255
282
  */
256
283
  class ConnectionQuality extends EventEmitter {
257
284
  /**
258
- * @param {Object} [config={}]
285
+ * @param {any} [config={}]
259
286
  */
260
287
  constructor(config = {}) {
261
288
  super();
289
+ /** @type {any} */
262
290
  this._config = { ...DEFAULT_CONFIG, ...config };
263
291
  /** @type {Map<string, PeerQualityTracker>} */
264
292
  this._peers = new Map();
293
+ /** @type {any} */
265
294
  this._updateTimer = null;
266
295
  }
267
296
 
@@ -301,7 +330,7 @@ class ConnectionQuality extends EventEmitter {
301
330
  if (!this._peers.has(peerId)) {
302
331
  this._peers.set(peerId, new PeerQualityTracker(peerId, this._config));
303
332
  }
304
- return this._peers.get(peerId);
333
+ return /** @type {PeerQualityTracker} */ (this._peers.get(peerId));
305
334
  }
306
335
 
307
336
  /**
@@ -367,7 +396,7 @@ class ConnectionQuality extends EventEmitter {
367
396
  /**
368
397
  * Gets quality for a specific peer
369
398
  * @param {string} peerId
370
- * @returns {Object|null}
399
+ * @returns {any}
371
400
  */
372
401
  getQuality(peerId) {
373
402
  const tracker = this._peers.get(peerId);
@@ -377,7 +406,7 @@ class ConnectionQuality extends EventEmitter {
377
406
 
378
407
  /**
379
408
  * Gets quality for all peers
380
- * @returns {Object[]}
409
+ * @returns {any[]}
381
410
  */
382
411
  getAllQuality() {
383
412
  const results = [];
@@ -388,10 +417,15 @@ class ConnectionQuality extends EventEmitter {
388
417
  }
389
418
 
390
419
  /**
391
- * Periodic update — recalculates all qualities and emits changes
420
+ * Periodic update — recalculates all qualities and emits changes.
421
+ * Stops the timer automatically when no peers are connected.
392
422
  * @private
393
423
  */
394
424
  _update() {
425
+ if (this._peers.size === 0) {
426
+ this.stop();
427
+ return;
428
+ }
395
429
  for (const tracker of this._peers.values()) {
396
430
  const quality = tracker.calculate();
397
431
  if (quality.changed) {
@@ -12,7 +12,7 @@ const EventEmitter = require('../../utils/EventEmitter');
12
12
 
13
13
  /**
14
14
  * Health status levels
15
- * @constant {Object}
15
+ * @constant {any}
16
16
  */
17
17
  const HEALTH_STATUS = Object.freeze({
18
18
  GOOD: 'good',
@@ -23,7 +23,7 @@ const HEALTH_STATUS = Object.freeze({
23
23
 
24
24
  /**
25
25
  * Default monitoring configuration
26
- * @constant {Object}
26
+ * @constant {any}
27
27
  */
28
28
  const DEFAULT_CONFIG = Object.freeze({
29
29
  /** Sample window size for latency calculations */
@@ -90,21 +90,21 @@ const DEFAULT_CONFIG = Object.freeze({
90
90
  class NetworkMonitor extends EventEmitter {
91
91
  /**
92
92
  * Creates a new NetworkMonitor instance.
93
- * @param {Object} [options={}] - Configuration options
93
+ * @param {any} [options={}] - Configuration options
94
94
  */
95
95
  constructor(options = {}) {
96
96
  super();
97
97
 
98
98
  /**
99
99
  * Configuration
100
- * @type {Object}
100
+ * @type {any}
101
101
  * @private
102
102
  */
103
103
  this._config = { ...DEFAULT_CONFIG, ...options };
104
104
 
105
105
  /**
106
106
  * Node health tracking
107
- * @type {Map<string, NodeHealth>}
107
+ * @type {Map<string, any>}
108
108
  * @private
109
109
  */
110
110
  this._nodes = new Map();
@@ -117,15 +117,36 @@ class NetworkMonitor extends EventEmitter {
117
117
  this._pendingMessages = new Map();
118
118
 
119
119
  /**
120
- * Latency samples
121
- * @type {number[]}
120
+ * Latency samples (circular buffer)
121
+ * @type {Float64Array}
122
122
  * @private
123
123
  */
124
- this._latencies = [];
124
+ this._latencies = new Float64Array(this._config.latencySampleSize);
125
+
126
+ /**
127
+ * Circular buffer write index
128
+ * @type {number}
129
+ * @private
130
+ */
131
+ this._latencyIndex = 0;
132
+
133
+ /**
134
+ * Number of latency samples stored
135
+ * @type {number}
136
+ * @private
137
+ */
138
+ this._latencyCount = 0;
139
+
140
+ /**
141
+ * Running sum of latency samples for O(1) average
142
+ * @type {number}
143
+ * @private
144
+ */
145
+ this._latencySum = 0;
125
146
 
126
147
  /**
127
148
  * Global statistics
128
- * @type {Object}
149
+ * @type {any}
129
150
  * @private
130
151
  */
131
152
  this._stats = {
@@ -137,7 +158,7 @@ class NetworkMonitor extends EventEmitter {
137
158
 
138
159
  /**
139
160
  * Health check timer
140
- * @type {number|null}
161
+ * @type {any}
141
162
  * @private
142
163
  */
143
164
  this._healthCheckTimer = null;
@@ -149,6 +170,13 @@ class NetworkMonitor extends EventEmitter {
149
170
  */
150
171
  this._lastHealthReport = null;
151
172
 
173
+ /**
174
+ * Previous health status for change detection
175
+ * @type {string|null}
176
+ * @private
177
+ */
178
+ this._previousHealth = null;
179
+
152
180
  // Start health check timer
153
181
  this._startHealthCheck();
154
182
  }
@@ -330,7 +358,7 @@ class NetworkMonitor extends EventEmitter {
330
358
  /**
331
359
  * Gets detailed health for a specific node.
332
360
  * @param {string} peerId - Peer ID
333
- * @returns {NodeHealth|null} Node health or null
361
+ * @returns {any} Node health or null
334
362
  */
335
363
  getNodeHealth(peerId) {
336
364
  const node = this._nodes.get(peerId);
@@ -347,13 +375,13 @@ class NetworkMonitor extends EventEmitter {
347
375
 
348
376
  /**
349
377
  * Gets health information for all nodes.
350
- * @returns {NodeHealth[]} Array of node health
378
+ * @returns {any[]} Array of node health
351
379
  */
352
380
  getAllNodeHealth() {
353
381
  const now = Date.now();
354
382
  const timeout = this._config.nodeTimeoutMs;
355
383
 
356
- return Array.from(this._nodes.values()).map(node => ({
384
+ return Array.from(this._nodes.values()).map((/** @type {any} */ node) => ({
357
385
  ...node,
358
386
  isActive: (now - node.lastSeen) < timeout
359
387
  }));
@@ -369,7 +397,7 @@ class NetworkMonitor extends EventEmitter {
369
397
 
370
398
  /**
371
399
  * Gets monitoring statistics.
372
- * @returns {Object} Statistics
400
+ * @returns {any} Statistics
373
401
  */
374
402
  getStats() {
375
403
  return {
@@ -386,7 +414,10 @@ class NetworkMonitor extends EventEmitter {
386
414
  reset() {
387
415
  this._nodes.clear();
388
416
  this._pendingMessages.clear();
389
- this._latencies = [];
417
+ this._latencies = new Float64Array(this._config.latencySampleSize);
418
+ this._latencyIndex = 0;
419
+ this._latencyCount = 0;
420
+ this._latencySum = 0;
390
421
  this._stats = {
391
422
  totalMessagesSent: 0,
392
423
  totalMessagesDelivered: 0,
@@ -409,7 +440,7 @@ class NetworkMonitor extends EventEmitter {
409
440
  /**
410
441
  * Gets or creates a node entry.
411
442
  * @param {string} peerId - Peer ID
412
- * @returns {NodeHealth} Node entry
443
+ * @returns {any} Node entry
413
444
  * @private
414
445
  */
415
446
  _getOrCreateNode(peerId) {
@@ -430,20 +461,27 @@ class NetworkMonitor extends EventEmitter {
430
461
  }
431
462
 
432
463
  /**
433
- * Adds a latency sample.
464
+ * Adds a latency sample using circular buffer.
434
465
  * @param {number} latency - Latency in ms
435
466
  * @private
436
467
  */
437
468
  _addLatencySample(latency) {
438
- this._latencies.push(latency);
439
- if (this._latencies.length > this._config.latencySampleSize) {
440
- this._latencies.shift();
469
+ const capacity = this._latencies.length;
470
+ // Subtract the old value being overwritten if buffer is full
471
+ if (this._latencyCount >= capacity) {
472
+ this._latencySum -= this._latencies[this._latencyIndex];
473
+ }
474
+ this._latencies[this._latencyIndex] = latency;
475
+ this._latencySum += latency;
476
+ this._latencyIndex = (this._latencyIndex + 1) % capacity;
477
+ if (this._latencyCount < capacity) {
478
+ this._latencyCount++;
441
479
  }
442
480
  }
443
481
 
444
482
  /**
445
483
  * Updates node latency with exponential moving average.
446
- * @param {NodeHealth} node - Node to update
484
+ * @param {any} node - Node to update
447
485
  * @param {number} latency - New latency sample
448
486
  * @private
449
487
  */
@@ -458,7 +496,7 @@ class NetworkMonitor extends EventEmitter {
458
496
 
459
497
  /**
460
498
  * Updates node packet loss rate.
461
- * @param {NodeHealth} node - Node to update
499
+ * @param {any} node - Node to update
462
500
  * @private
463
501
  */
464
502
  _updateNodePacketLoss(node) {
@@ -469,17 +507,30 @@ class NetworkMonitor extends EventEmitter {
469
507
  }
470
508
 
471
509
  /**
472
- * Calculates average latency from samples.
510
+ * Calculates average latency from samples (O(1) using running sum).
473
511
  * @returns {number} Average latency
474
512
  * @private
475
513
  */
476
514
  _calculateAverageLatency() {
477
- if (this._latencies.length === 0) {
515
+ if (this._latencyCount === 0) {
478
516
  return 0;
479
517
  }
480
- return Math.round(
481
- this._latencies.reduce((a, b) => a + b, 0) / this._latencies.length
482
- );
518
+ return Math.round(this._latencySum / this._latencyCount);
519
+ }
520
+
521
+ /**
522
+ * Cleans up stale pending messages older than nodeTimeoutMs.
523
+ * @private
524
+ */
525
+ _cleanupPendingMessages() {
526
+ const now = Date.now();
527
+ const timeout = this._config.nodeTimeoutMs;
528
+ for (const [messageId, pending] of this._pendingMessages) {
529
+ if (now - pending.timestamp > timeout) {
530
+ this._pendingMessages.delete(messageId);
531
+ this._stats.totalMessagesFailed++;
532
+ }
533
+ }
483
534
  }
484
535
 
485
536
  /**
@@ -520,9 +571,10 @@ class NetworkMonitor extends EventEmitter {
520
571
  this._healthCheckTimer = setInterval(
521
572
  () => {
522
573
  try {
574
+ this._cleanupPendingMessages();
523
575
  const report = this.generateHealthReport();
524
576
  this.emit('health-report', report);
525
- } catch (error) {
577
+ } catch (_error) {
526
578
  // Don't let health check errors crash the monitor
527
579
  }
528
580
  },
@@ -8,6 +8,9 @@
8
8
  const { CONNECTION_STATE } = require('../../constants');
9
9
  const { ValidationError } = require('../../errors');
10
10
 
11
+ /** Pre-computed Set of valid connection states for O(1) lookup */
12
+ const CONNECTION_STATE_SET = new Set(Object.values(CONNECTION_STATE));
13
+
11
14
  /**
12
15
  * Represents a peer in the mesh network
13
16
  * @class Peer
@@ -15,12 +18,7 @@ const { ValidationError } = require('../../errors');
15
18
  class Peer {
16
19
  /**
17
20
  * Creates a new Peer
18
- * @param {Object} options - Peer options
19
- * @param {string} options.id - Unique peer identifier
20
- * @param {Uint8Array} [options.publicKey] - Peer's public key
21
- * @param {string} [options.name] - Display name
22
- * @param {number} [options.rssi] - Signal strength
23
- * @param {number} [options.hopCount] - Distance in hops
21
+ * @param {any} options - Peer options *
24
22
  */
25
23
  constructor(options) {
26
24
  if (!options || typeof options.id !== 'string' || options.id.length === 0) {
@@ -85,7 +83,7 @@ class Peer {
85
83
 
86
84
  /**
87
85
  * Additional metadata
88
- * @type {Object}
86
+ * @type {any}
89
87
  */
90
88
  this.metadata = options.metadata || {};
91
89
  }
@@ -130,9 +128,9 @@ class Peer {
130
128
  * @param {string} state - New connection state
131
129
  */
132
130
  setConnectionState(state) {
133
- if (!Object.values(CONNECTION_STATE).includes(state)) {
131
+ if (!CONNECTION_STATE_SET.has(state)) {
134
132
  throw ValidationError.invalidArgument('state', state, {
135
- validValues: Object.values(CONNECTION_STATE)
133
+ validValues: Array.from(CONNECTION_STATE_SET)
136
134
  });
137
135
  }
138
136
  this.connectionState = state;
@@ -198,7 +196,7 @@ class Peer {
198
196
 
199
197
  /**
200
198
  * Converts peer to a JSON-serializable object
201
- * @returns {Object} JSON representation
199
+ * @returns {any} JSON representation
202
200
  */
203
201
  toJSON() {
204
202
  return {
@@ -219,7 +217,7 @@ class Peer {
219
217
 
220
218
  /**
221
219
  * Creates a Peer from JSON data
222
- * @param {Object} data - JSON data
220
+ * @param {any} data - JSON data
223
221
  * @returns {Peer} New Peer instance
224
222
  */
225
223
  static fromJSON(data) {
@@ -16,7 +16,7 @@ const { ValidationError } = require('../../errors');
16
16
  * @property {string} [name] - Display name
17
17
  * @property {number[]} [publicKey] - Public key bytes
18
18
  * @property {number} [hopCount] - Hop count
19
- * @property {Object} [capabilities] - Peer capabilities
19
+ * @property {any} [capabilities] - Peer capabilities
20
20
  */
21
21
 
22
22
  /**
@@ -27,10 +27,7 @@ const { ValidationError } = require('../../errors');
27
27
  class PeerDiscovery extends EventEmitter {
28
28
  /**
29
29
  * Creates a new PeerDiscovery handler
30
- * @param {Object} options - Configuration options
31
- * @param {string} options.localPeerId - Local peer's ID
32
- * @param {Uint8Array} [options.publicKey] - Local peer's public key
33
- * @param {string} [options.displayName] - Local display name
30
+ * @param {any} options - Configuration options *
34
31
  */
35
32
  constructor(options = {}) {
36
33
  super();
@@ -59,13 +56,13 @@ class PeerDiscovery extends EventEmitter {
59
56
 
60
57
  /**
61
58
  * Capabilities advertised to peers
62
- * @type {Object}
59
+ * @type {any}
63
60
  */
64
61
  this.capabilities = options.capabilities || {};
65
62
 
66
63
  /**
67
64
  * Discovery statistics
68
- * @type {Object}
65
+ * @type {any}
69
66
  * @private
70
67
  */
71
68
  this._stats = {
@@ -80,9 +77,10 @@ class PeerDiscovery extends EventEmitter {
80
77
 
81
78
  /**
82
79
  * Creates an announce message payload
83
- * @returns {Object} Announce payload
80
+ * @returns {any} Announce payload
84
81
  */
85
82
  createAnnouncePayload() {
83
+ /** @type {any} */
86
84
  const payload = {
87
85
  peerId: this.localPeerId,
88
86
  name: this.displayName,
@@ -100,8 +98,9 @@ class PeerDiscovery extends EventEmitter {
100
98
  /**
101
99
  * Creates a peer request payload
102
100
  * @param {string} [targetPeerId] - Specific peer to request (null for broadcast)
103
- * @returns {Object} Request payload
101
+ * @returns {any} Request payload
104
102
  */
103
+ // @ts-ignore
105
104
  createRequestPayload(targetPeerId = null) {
106
105
  return {
107
106
  requesterId: this.localPeerId,
@@ -113,7 +112,7 @@ class PeerDiscovery extends EventEmitter {
113
112
  /**
114
113
  * Creates a peer response payload
115
114
  * @param {string} requesterId - ID of requesting peer
116
- * @returns {Object} Response payload
115
+ * @returns {any} Response payload
117
116
  */
118
117
  createResponsePayload(requesterId) {
119
118
  return {
@@ -129,9 +128,9 @@ class PeerDiscovery extends EventEmitter {
129
128
  /**
130
129
  * Processes an incoming discovery message
131
130
  * @param {number} type - Message type
132
- * @param {Object} payload - Message payload
131
+ * @param {any} payload - Message payload
133
132
  * @param {string} sourcePeerId - Source peer ID
134
- * @returns {Object|null} Response to send, or null
133
+ * @returns {any} Response to send, or null
135
134
  */
136
135
  processMessage(type, payload, sourcePeerId) {
137
136
  // Ignore our own messages
@@ -158,7 +157,7 @@ class PeerDiscovery extends EventEmitter {
158
157
 
159
158
  /**
160
159
  * Handles a peer announce message
161
- * @param {Object} payload - Announce payload
160
+ * @param {any} payload - Announce payload
162
161
  * @param {string} sourcePeerId - Source peer ID
163
162
  * @returns {null} No response needed
164
163
  * @private
@@ -181,9 +180,9 @@ class PeerDiscovery extends EventEmitter {
181
180
 
182
181
  /**
183
182
  * Handles a peer request message
184
- * @param {Object} payload - Request payload
185
- * @param {string} sourcePeerId - Source peer ID
186
- * @returns {Object|null} Response payload or null
183
+ * @param {any} payload - Request payload
184
+ * @param {string} _sourcePeerId - Source peer ID
185
+ * @returns {any} Response payload or null
187
186
  * @private
188
187
  */
189
188
  _handleRequest(payload, _sourcePeerId) {
@@ -203,7 +202,7 @@ class PeerDiscovery extends EventEmitter {
203
202
 
204
203
  /**
205
204
  * Handles a peer response message
206
- * @param {Object} payload - Response payload
205
+ * @param {any} payload - Response payload
207
206
  * @param {string} sourcePeerId - Source peer ID
208
207
  * @returns {null} No response needed
209
208
  * @private
@@ -230,7 +229,7 @@ class PeerDiscovery extends EventEmitter {
230
229
 
231
230
  /**
232
231
  * Updates local peer information
233
- * @param {Object} info - New info
232
+ * @param {any} info - New info
234
233
  */
235
234
  updateLocalInfo(info) {
236
235
  if (info.displayName !== undefined) { this.displayName = info.displayName; }
@@ -242,7 +241,7 @@ class PeerDiscovery extends EventEmitter {
242
241
 
243
242
  /**
244
243
  * Gets discovery statistics
245
- * @returns {Object} Statistics
244
+ * @returns {any} Statistics
246
245
  */
247
246
  getStats() {
248
247
  return { ...this._stats };