react-native-ble-mesh 2.1.0 → 2.1.3

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 (88) hide show
  1. package/package.json +9 -2
  2. package/src/MeshNetwork.js +48 -46
  3. package/src/constants/audio.js +4 -4
  4. package/src/constants/ble.js +1 -1
  5. package/src/constants/crypto.js +1 -1
  6. package/src/constants/errors.js +2 -2
  7. package/src/constants/events.js +1 -1
  8. package/src/constants/protocol.js +2 -2
  9. package/src/crypto/AutoCrypto.js +2 -0
  10. package/src/crypto/CryptoProvider.js +17 -17
  11. package/src/crypto/providers/ExpoCryptoProvider.js +12 -7
  12. package/src/crypto/providers/QuickCryptoProvider.js +50 -15
  13. package/src/crypto/providers/TweetNaClProvider.js +9 -7
  14. package/src/errors/AudioError.js +2 -1
  15. package/src/errors/ConnectionError.js +2 -2
  16. package/src/errors/CryptoError.js +1 -1
  17. package/src/errors/HandshakeError.js +2 -2
  18. package/src/errors/MeshError.js +4 -4
  19. package/src/errors/MessageError.js +2 -2
  20. package/src/errors/ValidationError.js +3 -3
  21. package/src/expo/withBLEMesh.js +10 -10
  22. package/src/hooks/AppStateManager.js +10 -4
  23. package/src/hooks/useMesh.js +7 -7
  24. package/src/hooks/useMessages.js +13 -12
  25. package/src/hooks/usePeers.js +10 -9
  26. package/src/index.js +2 -2
  27. package/src/mesh/dedup/BloomFilter.js +1 -0
  28. package/src/mesh/dedup/DedupManager.js +4 -7
  29. package/src/mesh/dedup/MessageCache.js +3 -0
  30. package/src/mesh/fragment/Assembler.js +5 -4
  31. package/src/mesh/fragment/Fragmenter.js +2 -2
  32. package/src/mesh/monitor/ConnectionQuality.js +17 -8
  33. package/src/mesh/monitor/NetworkMonitor.js +22 -15
  34. package/src/mesh/peer/Peer.js +4 -9
  35. package/src/mesh/peer/PeerDiscovery.js +18 -19
  36. package/src/mesh/peer/PeerManager.js +14 -14
  37. package/src/mesh/router/MessageRouter.js +15 -15
  38. package/src/mesh/router/PathFinder.js +10 -13
  39. package/src/mesh/router/RouteTable.js +8 -7
  40. package/src/mesh/store/StoreAndForwardManager.js +20 -23
  41. package/src/protocol/message.js +5 -13
  42. package/src/protocol/serializer.js +4 -4
  43. package/src/protocol/validator.js +7 -6
  44. package/src/service/BatteryOptimizer.js +18 -17
  45. package/src/service/EmergencyManager.js +19 -26
  46. package/src/service/HandshakeManager.js +100 -2
  47. package/src/service/MeshService.js +106 -22
  48. package/src/service/SessionManager.js +38 -3
  49. package/src/service/audio/AudioManager.js +80 -38
  50. package/src/service/audio/buffer/FrameBuffer.js +7 -8
  51. package/src/service/audio/buffer/JitterBuffer.js +1 -1
  52. package/src/service/audio/codec/LC3Codec.js +22 -20
  53. package/src/service/audio/codec/LC3Decoder.js +10 -10
  54. package/src/service/audio/codec/LC3Encoder.js +11 -9
  55. package/src/service/audio/session/AudioSession.js +14 -17
  56. package/src/service/audio/session/VoiceMessage.js +15 -22
  57. package/src/service/audio/transport/AudioFragmenter.js +17 -9
  58. package/src/service/audio/transport/AudioFramer.js +8 -12
  59. package/src/service/file/FileAssembler.js +4 -2
  60. package/src/service/file/FileChunker.js +1 -1
  61. package/src/service/file/FileManager.js +26 -20
  62. package/src/service/file/FileMessage.js +7 -12
  63. package/src/service/text/TextManager.js +55 -28
  64. package/src/service/text/broadcast/BroadcastManager.js +14 -17
  65. package/src/service/text/channel/Channel.js +10 -14
  66. package/src/service/text/channel/ChannelManager.js +10 -10
  67. package/src/service/text/message/TextMessage.js +12 -19
  68. package/src/service/text/message/TextSerializer.js +2 -2
  69. package/src/storage/AsyncStorageAdapter.js +17 -14
  70. package/src/storage/MemoryStorage.js +11 -8
  71. package/src/storage/MessageStore.js +22 -30
  72. package/src/storage/Storage.js +9 -9
  73. package/src/transport/BLETransport.js +16 -14
  74. package/src/transport/MockTransport.js +7 -2
  75. package/src/transport/MultiTransport.js +13 -6
  76. package/src/transport/Transport.js +9 -9
  77. package/src/transport/WiFiDirectTransport.js +25 -24
  78. package/src/transport/adapters/BLEAdapter.js +19 -19
  79. package/src/transport/adapters/NodeBLEAdapter.js +24 -23
  80. package/src/transport/adapters/RNBLEAdapter.js +19 -24
  81. package/src/utils/EventEmitter.js +17 -12
  82. package/src/utils/LRUCache.js +10 -4
  83. package/src/utils/RateLimiter.js +1 -1
  84. package/src/utils/compression.js +6 -8
  85. package/src/utils/encoding.js +8 -2
  86. package/src/utils/retry.js +11 -13
  87. package/src/utils/time.js +9 -4
  88. package/src/utils/validation.js +1 -1
@@ -18,7 +18,7 @@ const { unpackFrame, createStreamFrame } = require('./transport/AudioFramer');
18
18
 
19
19
  /**
20
20
  * Audio manager states
21
- * @constant {Object}
21
+ * @constant {any}
22
22
  */
23
23
  const MANAGER_STATE = Object.freeze({
24
24
  UNINITIALIZED: 'uninitialized',
@@ -37,28 +37,29 @@ const MANAGER_STATE = Object.freeze({
37
37
  class AudioManager extends EventEmitter {
38
38
  /**
39
39
  * Creates a new AudioManager
40
- * @param {Object} [options] - Manager options
41
- * @param {string} [options.quality='MEDIUM'] - Audio quality preset
40
+ * @param {any} [options] - Manager options
42
41
  */
43
42
  constructor(options = {}) {
44
43
  super();
45
44
 
46
- /** @private */
45
+ /** @type {string} @private */
47
46
  this._quality = options.quality || 'MEDIUM';
48
- /** @private */
47
+ /** @type {string} @private */
49
48
  this._state = MANAGER_STATE.UNINITIALIZED;
50
- /** @private */
49
+ /** @type {any} @private */
51
50
  this._meshService = null;
52
- /** @private */
51
+ /** @type {any} @private */
53
52
  this._codec = null;
54
- /** @private */
53
+ /** @type {Map<string, any>} @private */
55
54
  this._sessions = new Map(); // peerId -> AudioSession
56
- /** @private */
55
+ /** @type {Map<string, any>} @private */
57
56
  this._pendingRequests = new Map(); // peerId -> { resolve, reject, timeout }
58
57
  /** @private */
59
58
  this._voiceAssembler = new AudioAssembler();
60
- /** @private */
59
+ /** @type {any} @private */
61
60
  this._senderId = null;
61
+ /** @type {string|undefined} @private */
62
+ this._lastVoiceMessagePeerId = undefined;
62
63
 
63
64
  this._setupAssemblerEvents();
64
65
  }
@@ -68,15 +69,15 @@ class AudioManager extends EventEmitter {
68
69
  * @private
69
70
  */
70
71
  _setupAssemblerEvents() {
71
- this._voiceAssembler.on('complete', (data) => {
72
+ this._voiceAssembler.on('complete', (/** @type {any} */ data) => {
72
73
  this._handleVoiceMessageComplete(data);
73
74
  });
74
75
 
75
- this._voiceAssembler.on('progress', (data) => {
76
+ this._voiceAssembler.on('progress', (/** @type {any} */ data) => {
76
77
  this.emit(EVENTS.VOICE_MESSAGE_PROGRESS, data);
77
78
  });
78
79
 
79
- this._voiceAssembler.on('timeout', (data) => {
80
+ this._voiceAssembler.on('timeout', (/** @type {any} */ data) => {
80
81
  this.emit(EVENTS.VOICE_MESSAGE_FAILED, {
81
82
  ...data,
82
83
  error: AudioError.voiceMessageTimeout(data.messageId)
@@ -86,7 +87,7 @@ class AudioManager extends EventEmitter {
86
87
 
87
88
  /**
88
89
  * Initializes the audio manager
89
- * @param {MeshService} meshService - Mesh service instance
90
+ * @param {any} meshService - Mesh service instance
90
91
  * @returns {Promise<void>}
91
92
  */
92
93
  async initialize(meshService) {
@@ -104,13 +105,13 @@ class AudioManager extends EventEmitter {
104
105
  this._senderId = identity.publicKey || new Uint8Array(32);
105
106
 
106
107
  // Initialize codec
107
- const qualityConfig = AUDIO_QUALITY[this._quality];
108
+ const qualityConfig = /** @type {any} */ (AUDIO_QUALITY)[this._quality];
108
109
  this._codec = new LC3Codec(qualityConfig);
109
110
  await this._codec.initialize();
110
111
 
111
112
  this._setState(MANAGER_STATE.READY);
112
113
  this.emit('initialized', { quality: this._quality, codec: this._codec.getConfig() });
113
- } catch (error) {
114
+ } catch (/** @type {any} */ error) {
114
115
  this._setState(MANAGER_STATE.ERROR);
115
116
  throw AudioError.codecInitFailed({ reason: error.message });
116
117
  }
@@ -122,6 +123,7 @@ class AudioManager extends EventEmitter {
122
123
  */
123
124
  async destroy() {
124
125
  // End all sessions and wait for completion
126
+ /** @type {Promise<void>[]} */
125
127
  const endPromises = [];
126
128
  for (const [, session] of this._sessions) {
127
129
  if (session && typeof session.end === 'function') {
@@ -156,7 +158,8 @@ class AudioManager extends EventEmitter {
156
158
  * @param {string} quality - Quality preset (LOW, MEDIUM, HIGH)
157
159
  */
158
160
  setQuality(quality) {
159
- if (!AUDIO_QUALITY[quality]) {
161
+ const qualities = /** @type {any} */ (AUDIO_QUALITY);
162
+ if (!qualities[quality]) {
160
163
  throw AudioError.invalidConfig(`Unknown quality: ${quality}`);
161
164
  }
162
165
  this._quality = quality;
@@ -172,7 +175,7 @@ class AudioManager extends EventEmitter {
172
175
 
173
176
  /**
174
177
  * Returns codec info
175
- * @returns {Object|null}
178
+ * @returns {any}
176
179
  */
177
180
  getCodecInfo() {
178
181
  return this._codec ? this._codec.getConfig() : null;
@@ -181,7 +184,7 @@ class AudioManager extends EventEmitter {
181
184
  /**
182
185
  * Requests an audio stream with a peer
183
186
  * @param {string} peerId - Remote peer ID
184
- * @returns {Promise<AudioSession>}
187
+ * @returns {Promise<any>}
185
188
  */
186
189
  async requestStream(peerId) {
187
190
  this._validateReady();
@@ -194,7 +197,7 @@ class AudioManager extends EventEmitter {
194
197
  peerId,
195
198
  codec: this._codec,
196
199
  isInitiator: true,
197
- sendCallback: (data) => this._sendStreamData(data)
200
+ sendCallback: (/** @type {any} */ data) => this._sendStreamData(data)
198
201
  });
199
202
 
200
203
  session.setRequesting();
@@ -219,7 +222,7 @@ class AudioManager extends EventEmitter {
219
222
  /**
220
223
  * Accepts an incoming stream request
221
224
  * @param {string} peerId - Remote peer ID
222
- * @returns {Promise<AudioSession>}
225
+ * @returns {Promise<any>}
223
226
  */
224
227
  async acceptStream(peerId) {
225
228
  this._validateReady();
@@ -270,7 +273,7 @@ class AudioManager extends EventEmitter {
270
273
  /**
271
274
  * Gets a session by peer ID
272
275
  * @param {string} peerId - Peer ID
273
- * @returns {AudioSession|undefined}
276
+ * @returns {any}
274
277
  */
275
278
  getSession(peerId) {
276
279
  return this._sessions.get(peerId);
@@ -278,11 +281,11 @@ class AudioManager extends EventEmitter {
278
281
 
279
282
  /**
280
283
  * Gets all active sessions
281
- * @returns {AudioSession[]}
284
+ * @returns {any[]}
282
285
  */
283
286
  getActiveSessions() {
284
287
  return Array.from(this._sessions.values())
285
- .filter(s => s.getState() === AUDIO_SESSION_STATE.ACTIVE);
288
+ .filter((/** @type {any} */ s) => s.getState() === AUDIO_SESSION_STATE.ACTIVE);
286
289
  }
287
290
 
288
291
  /**
@@ -301,7 +304,7 @@ class AudioManager extends EventEmitter {
301
304
  /**
302
305
  * Sends a voice message to a peer
303
306
  * @param {string} peerId - Remote peer ID
304
- * @param {VoiceMessage} message - Voice message to send
307
+ * @param {any} message - Voice message to send
305
308
  * @returns {Promise<string>} Message ID
306
309
  */
307
310
  async sendVoiceMessage(peerId, message) {
@@ -353,7 +356,10 @@ class AudioManager extends EventEmitter {
353
356
  }
354
357
  }
355
358
 
356
- /** @private */
359
+ /**
360
+ * @param {string} peerId
361
+ * @private
362
+ */
357
363
  _handleStreamRequest(peerId) {
358
364
  if (this._sessions.has(peerId)) { return; }
359
365
 
@@ -361,7 +367,7 @@ class AudioManager extends EventEmitter {
361
367
  peerId,
362
368
  codec: this._codec,
363
369
  isInitiator: false,
364
- sendCallback: (data) => this._sendStreamData(data)
370
+ sendCallback: (/** @type {any} */ data) => this._sendStreamData(data)
365
371
  });
366
372
 
367
373
  session.setPending();
@@ -370,7 +376,10 @@ class AudioManager extends EventEmitter {
370
376
  this.emit(EVENTS.AUDIO_STREAM_REQUEST, { peerId });
371
377
  }
372
378
 
373
- /** @private */
379
+ /**
380
+ * @param {string} peerId
381
+ * @private
382
+ */
374
383
  _handleStreamAccept(peerId) {
375
384
  const request = this._pendingRequests.get(peerId);
376
385
  if (request) {
@@ -383,7 +392,11 @@ class AudioManager extends EventEmitter {
383
392
  }
384
393
  }
385
394
 
386
- /** @private */
395
+ /**
396
+ * @param {string} peerId
397
+ * @param {Uint8Array} payload
398
+ * @private
399
+ */
387
400
  _handleStreamReject(peerId, payload) {
388
401
  const request = this._pendingRequests.get(peerId);
389
402
  if (request) {
@@ -395,20 +408,27 @@ class AudioManager extends EventEmitter {
395
408
  }
396
409
  }
397
410
 
398
- /** @private */
411
+ /**
412
+ * @param {string} peerId
413
+ * @param {Uint8Array} payload
414
+ * @private
415
+ */
399
416
  _handleStreamData(peerId, payload) {
400
417
  const session = this._sessions.get(peerId);
401
418
  if (session && session.getState() === AUDIO_SESSION_STATE.ACTIVE) {
402
419
  try {
403
420
  const { frame, sequenceNumber, timestampDelta } = unpackFrame(payload);
404
421
  session.receiveAudio(frame, sequenceNumber, timestampDelta);
405
- } catch (error) {
422
+ } catch (/** @type {any} */ error) {
406
423
  this.emit('error', error);
407
424
  }
408
425
  }
409
426
  }
410
427
 
411
- /** @private */
428
+ /**
429
+ * @param {string} peerId
430
+ * @private
431
+ */
412
432
  _handleStreamEnd(peerId) {
413
433
  const session = this._sessions.get(peerId);
414
434
  if (session) {
@@ -418,7 +438,11 @@ class AudioManager extends EventEmitter {
418
438
  }
419
439
  }
420
440
 
421
- /** @private */
441
+ /**
442
+ * @param {string} peerId
443
+ * @param {Uint8Array} payload
444
+ * @private
445
+ */
422
446
  _handleVoiceMessageFragment(peerId, payload) {
423
447
  const fullPayload = new Uint8Array(payload.length + 1);
424
448
  fullPayload[0] = payload[0]; // type is already in payload for fragments
@@ -431,7 +455,10 @@ class AudioManager extends EventEmitter {
431
455
  }
432
456
  }
433
457
 
434
- /** @private */
458
+ /**
459
+ * @param {any} param0
460
+ * @private
461
+ */
435
462
  _handleVoiceMessageComplete({ messageId, size }) {
436
463
  // Note: The actual voice message data comes from the assembler
437
464
  this.emit(EVENTS.VOICE_MESSAGE_RECEIVED, {
@@ -441,13 +468,21 @@ class AudioManager extends EventEmitter {
441
468
  });
442
469
  }
443
470
 
444
- /** @private */
471
+ /**
472
+ * @param {any} param0
473
+ * @private
474
+ */
445
475
  async _sendStreamData({ peerId, frame, sequenceNumber, timestampDelta }) {
446
476
  const packed = createStreamFrame(frame, sequenceNumber, timestampDelta);
447
477
  await this._sendRaw(peerId, packed);
448
478
  }
449
479
 
450
- /** @private */
480
+ /**
481
+ * @param {string} peerId
482
+ * @param {number} type
483
+ * @param {Uint8Array} payload
484
+ * @private
485
+ */
451
486
  async _sendMessage(peerId, type, payload) {
452
487
  const data = new Uint8Array(1 + payload.length);
453
488
  data[0] = type;
@@ -455,7 +490,11 @@ class AudioManager extends EventEmitter {
455
490
  await this._sendRaw(peerId, data);
456
491
  }
457
492
 
458
- /** @private */
493
+ /**
494
+ * @param {string} peerId
495
+ * @param {Uint8Array} data
496
+ * @private
497
+ */
459
498
  async _sendRaw(peerId, data) {
460
499
  if (this._meshService && typeof this._meshService._sendRaw === 'function') {
461
500
  await this._meshService._sendRaw(peerId, data);
@@ -474,7 +513,10 @@ class AudioManager extends EventEmitter {
474
513
  }
475
514
  }
476
515
 
477
- /** @private */
516
+ /**
517
+ * @param {string} newState
518
+ * @private
519
+ */
478
520
  _setState(newState) {
479
521
  this._state = newState;
480
522
  }
@@ -14,18 +14,16 @@ const { VOICE_MESSAGE_CONFIG } = require('../../../constants/audio');
14
14
  class FrameBuffer {
15
15
  /**
16
16
  * Creates a new FrameBuffer
17
- * @param {Object} [options] - Buffer options
18
- * @param {number} [options.maxFrames=30000] - Maximum frames to store
19
- * @param {number} [options.maxBytes] - Maximum bytes to store
17
+ * @param {any} [options] - Buffer options
20
18
  */
21
19
  constructor(options = {}) {
22
- /** @private */
20
+ /** @type {number} @private */
23
21
  this._maxFrames = options.maxFrames || 30000;
24
- /** @private */
22
+ /** @type {number} @private */
25
23
  this._maxBytes = options.maxBytes || VOICE_MESSAGE_CONFIG.MAX_SIZE_BYTES;
26
- /** @private */
24
+ /** @type {Uint8Array[]} @private */
27
25
  this._frames = [];
28
- /** @private */
26
+ /** @type {number} @private */
29
27
  this._totalBytes = 0;
30
28
  }
31
29
 
@@ -99,6 +97,7 @@ class FrameBuffer {
99
97
  */
100
98
  serialize() {
101
99
  // Format: [frameCount(4)] + [frameLen(2) + frameData]...
100
+ /** @type {Uint8Array[]} */
102
101
  const parts = [];
103
102
  const countBytes = new Uint8Array(4);
104
103
  new DataView(countBytes.buffer).setUint32(0, this._frames.length, false);
@@ -111,7 +110,7 @@ class FrameBuffer {
111
110
  parts.push(frame);
112
111
  }
113
112
 
114
- const totalLen = parts.reduce((sum, p) => sum + p.length, 0);
113
+ const totalLen = parts.reduce((/** @type {number} */ sum, /** @type {Uint8Array} */ p) => sum + p.length, 0);
115
114
  const result = new Uint8Array(totalLen);
116
115
  let offset = 0;
117
116
 
@@ -149,7 +149,7 @@ class JitterBuffer extends EventEmitter {
149
149
 
150
150
  /**
151
151
  * Returns buffer statistics
152
- * @returns {Object}
152
+ * @returns {any}
153
153
  */
154
154
  getStats() {
155
155
  return {
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+ /* global __DEV__ */
2
3
 
3
4
  /**
4
5
  * @fileoverview LC3 codec wrapper for React Native
@@ -17,30 +18,27 @@ const { LC3_CONFIG, AUDIO_QUALITY } = require('../../../constants/audio');
17
18
  class LC3Codec extends EventEmitter {
18
19
  /**
19
20
  * Creates a new LC3Codec instance
20
- * @param {Object} [options] - Codec configuration
21
- * @param {number} [options.sampleRate=16000] - Sample rate in Hz
22
- * @param {number} [options.frameMs=10] - Frame duration in milliseconds
23
- * @param {number} [options.bitRate=24000] - Bit rate in bps
24
- * @param {number} [options.channels=1] - Number of audio channels
21
+ * @param {any} [options] - Codec configuration
25
22
  */
26
23
  constructor(options = {}) {
27
24
  super();
28
25
 
29
- const quality = options.quality ? AUDIO_QUALITY[options.quality] : null;
26
+ /** @type {any} */
27
+ const quality = options.quality ? /** @type {any} */ (AUDIO_QUALITY)[options.quality] : null;
30
28
 
31
- /** @private */
29
+ /** @type {number} @private */
32
30
  this._sampleRate = quality?.sampleRate || options.sampleRate || LC3_CONFIG.DEFAULT_SAMPLE_RATE;
33
- /** @private */
31
+ /** @type {number} @private */
34
32
  this._frameMs = quality?.frameMs || options.frameMs || LC3_CONFIG.DEFAULT_FRAME_DURATION_MS;
35
- /** @private */
33
+ /** @type {number} @private */
36
34
  this._bitRate = quality?.bitRate || options.bitRate || LC3_CONFIG.DEFAULT_BIT_RATE;
37
- /** @private */
35
+ /** @type {number} @private */
38
36
  this._channels = quality?.channels || options.channels || LC3_CONFIG.DEFAULT_CHANNELS;
39
- /** @private */
37
+ /** @type {boolean} @private */
40
38
  this._initialized = false;
41
- /** @private */
39
+ /** @type {any} @private */
42
40
  this._nativeModule = null;
43
- /** @private */
41
+ /** @type {boolean} @private */
44
42
  this._useMock = false;
45
43
 
46
44
  this._validateConfig();
@@ -82,12 +80,14 @@ class LC3Codec extends EventEmitter {
82
80
  } else {
83
81
  // Use mock implementation for testing
84
82
  this._useMock = true;
85
- console.warn('LC3Codec: Native module not available, using mock implementation');
83
+ if (typeof __DEV__ !== 'undefined' && __DEV__) {
84
+ console.warn('LC3Codec: Native module not available, using mock implementation');
85
+ }
86
86
  }
87
87
 
88
88
  this._initialized = true;
89
89
  this.emit('initialized', this.getConfig());
90
- } catch (error) {
90
+ } catch (/** @type {any} */ error) {
91
91
  throw AudioError.codecInitFailed({ reason: error.message });
92
92
  }
93
93
  }
@@ -95,7 +95,7 @@ class LC3Codec extends EventEmitter {
95
95
  /**
96
96
  * Attempts to load the native LC3 module
97
97
  * @private
98
- * @returns {Object|null}
98
+ * @returns {any}
99
99
  */
100
100
  _loadNativeModule() {
101
101
  try {
@@ -150,7 +150,7 @@ class LC3Codec extends EventEmitter {
150
150
  try {
151
151
  const result = await this._nativeModule.encode(Array.from(pcmSamples));
152
152
  return new Uint8Array(result);
153
- } catch (error) {
153
+ } catch (/** @type {any} */ error) {
154
154
  throw AudioError.encodingFailed({ reason: error.message });
155
155
  }
156
156
  }
@@ -172,7 +172,7 @@ class LC3Codec extends EventEmitter {
172
172
  try {
173
173
  const result = await this._nativeModule.decode(Array.from(lc3Frame));
174
174
  return new Int16Array(result);
175
- } catch (error) {
175
+ } catch (/** @type {any} */ error) {
176
176
  throw AudioError.decodingFailed({ reason: error.message });
177
177
  }
178
178
  }
@@ -193,13 +193,14 @@ class LC3Codec extends EventEmitter {
193
193
  try {
194
194
  const result = await this._nativeModule.decodePLC();
195
195
  return new Int16Array(result);
196
- } catch (error) {
196
+ } catch (/** @type {any} */ error) {
197
197
  throw AudioError.decodingFailed({ reason: error.message });
198
198
  }
199
199
  }
200
200
 
201
201
  /**
202
202
  * Mock encode implementation for testing
203
+ * @param {Int16Array} pcmSamples
203
204
  * @private
204
205
  */
205
206
  _mockEncode(pcmSamples) {
@@ -217,6 +218,7 @@ class LC3Codec extends EventEmitter {
217
218
 
218
219
  /**
219
220
  * Mock decode implementation for testing
221
+ * @param {Uint8Array} lc3Frame
220
222
  * @private
221
223
  */
222
224
  _mockDecode(lc3Frame) {
@@ -261,7 +263,7 @@ class LC3Codec extends EventEmitter {
261
263
 
262
264
  /**
263
265
  * Returns the current codec configuration
264
- * @returns {Object}
266
+ * @returns {any}
265
267
  */
266
268
  getConfig() {
267
269
  return {
@@ -16,7 +16,7 @@ const AudioError = require('../../../errors/AudioError');
16
16
  class LC3Decoder extends EventEmitter {
17
17
  /**
18
18
  * Creates a new LC3Decoder
19
- * @param {LC3Codec} codec - Initialized LC3 codec instance
19
+ * @param {any} codec - Initialized LC3 codec instance
20
20
  */
21
21
  constructor(codec) {
22
22
  super();
@@ -25,17 +25,17 @@ class LC3Decoder extends EventEmitter {
25
25
  throw AudioError.codecInitFailed({ reason: 'Codec must be initialized' });
26
26
  }
27
27
 
28
- /** @private */
28
+ /** @type {any} @private */
29
29
  this._codec = codec;
30
- /** @private */
30
+ /** @type {number} @private */
31
31
  this._frameSamples = codec.getFrameSamples();
32
- /** @private */
32
+ /** @type {number} @private */
33
33
  this._framesDecoded = 0;
34
- /** @private */
34
+ /** @type {number} @private */
35
35
  this._plcFrames = 0;
36
- /** @private */
36
+ /** @type {number} @private */
37
37
  this._errors = 0;
38
- /** @private */
38
+ /** @type {number} @private */
39
39
  this._lastSequence = -1;
40
40
  }
41
41
 
@@ -63,7 +63,7 @@ class LC3Decoder extends EventEmitter {
63
63
  this._framesDecoded++;
64
64
  this.emit('samples', { samples, index: this._framesDecoded });
65
65
  return samples;
66
- } catch (error) {
66
+ } catch (/** @type {any} */ error) {
67
67
  this._errors++;
68
68
  this.emit('error', error);
69
69
  throw error;
@@ -80,7 +80,7 @@ class LC3Decoder extends EventEmitter {
80
80
  this._plcFrames++;
81
81
  this.emit('plc', { samples, plcCount: this._plcFrames });
82
82
  return samples;
83
- } catch (error) {
83
+ } catch (/** @type {any} */ error) {
84
84
  this._errors++;
85
85
  this.emit('error', error);
86
86
  // Return silence on PLC failure
@@ -106,7 +106,7 @@ class LC3Decoder extends EventEmitter {
106
106
 
107
107
  /**
108
108
  * Returns decoder statistics
109
- * @returns {Object}
109
+ * @returns {any}
110
110
  */
111
111
  getStats() {
112
112
  return {
@@ -16,7 +16,7 @@ const AudioError = require('../../../errors/AudioError');
16
16
  class LC3Encoder extends EventEmitter {
17
17
  /**
18
18
  * Creates a new LC3Encoder
19
- * @param {LC3Codec} codec - Initialized LC3 codec instance
19
+ * @param {any} codec - Initialized LC3 codec instance
20
20
  */
21
21
  constructor(codec) {
22
22
  super();
@@ -25,17 +25,17 @@ class LC3Encoder extends EventEmitter {
25
25
  throw AudioError.codecInitFailed({ reason: 'Codec must be initialized' });
26
26
  }
27
27
 
28
- /** @private */
28
+ /** @type {any} @private */
29
29
  this._codec = codec;
30
- /** @private */
30
+ /** @type {number} @private */
31
31
  this._frameSamples = codec.getFrameSamples();
32
32
  /** @private */
33
33
  this._sampleBuffer = new Int16Array(this._frameSamples * 2);
34
- /** @private */
34
+ /** @type {number} @private */
35
35
  this._bufferOffset = 0;
36
- /** @private */
36
+ /** @type {number} @private */
37
37
  this._framesEncoded = 0;
38
- /** @private */
38
+ /** @type {number} @private */
39
39
  this._errors = 0;
40
40
  }
41
41
 
@@ -45,6 +45,7 @@ class LC3Encoder extends EventEmitter {
45
45
  * @returns {Promise<Uint8Array[]>} Array of encoded LC3 frames
46
46
  */
47
47
  async pushSamples(samples) {
48
+ /** @type {Uint8Array[]} */
48
49
  const frames = [];
49
50
  let offset = 0;
50
51
 
@@ -68,7 +69,7 @@ class LC3Encoder extends EventEmitter {
68
69
  frames.push(encoded);
69
70
  this._framesEncoded++;
70
71
  this.emit('frame', { frame: encoded, index: this._framesEncoded });
71
- } catch (error) {
72
+ } catch (/** @type {any} */ error) {
72
73
  this._errors++;
73
74
  this.emit('error', error);
74
75
  }
@@ -84,6 +85,7 @@ class LC3Encoder extends EventEmitter {
84
85
  * @returns {Promise<Uint8Array[]>} Array of encoded LC3 frames
85
86
  */
86
87
  async flush() {
88
+ /** @type {Uint8Array[]} */
87
89
  const frames = [];
88
90
 
89
91
  if (this._bufferOffset > 0) {
@@ -96,7 +98,7 @@ class LC3Encoder extends EventEmitter {
96
98
  frames.push(encoded);
97
99
  this._framesEncoded++;
98
100
  this.emit('frame', { frame: encoded, index: this._framesEncoded, padded: true });
99
- } catch (error) {
101
+ } catch (/** @type {any} */ error) {
100
102
  this._errors++;
101
103
  this.emit('error', error);
102
104
  }
@@ -117,7 +119,7 @@ class LC3Encoder extends EventEmitter {
117
119
 
118
120
  /**
119
121
  * Returns encoder statistics
120
- * @returns {Object}
122
+ * @returns {any}
121
123
  */
122
124
  getStats() {
123
125
  return {