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
@@ -7,7 +7,7 @@
7
7
 
8
8
  /**
9
9
  * LC3 codec configuration
10
- * @constant {Object}
10
+ * @constant {any}
11
11
  */
12
12
  const LC3_CONFIG = Object.freeze({
13
13
  /** Supported sample rates (Hz) */
@@ -62,7 +62,7 @@ const AUDIO_QUALITY = Object.freeze({
62
62
 
63
63
  /**
64
64
  * Voice message configuration
65
- * @constant {Object}
65
+ * @constant {any}
66
66
  */
67
67
  const VOICE_MESSAGE_CONFIG = Object.freeze({
68
68
  /** Maximum voice message duration in seconds */
@@ -79,7 +79,7 @@ const VOICE_MESSAGE_CONFIG = Object.freeze({
79
79
 
80
80
  /**
81
81
  * Audio streaming configuration
82
- * @constant {Object}
82
+ * @constant {any}
83
83
  */
84
84
  const AUDIO_STREAM_CONFIG = Object.freeze({
85
85
  /** Default jitter buffer size in frames */
@@ -98,7 +98,7 @@ const AUDIO_STREAM_CONFIG = Object.freeze({
98
98
 
99
99
  /**
100
100
  * Audio session states
101
- * @constant {Object.<string, string>}
101
+ * @type {Record<string, string>}
102
102
  */
103
103
  const AUDIO_SESSION_STATE = Object.freeze({
104
104
  IDLE: 'idle',
@@ -77,7 +77,7 @@ const POWER_MODE = Object.freeze({
77
77
 
78
78
  /**
79
79
  * Bluetooth adapter states
80
- * @constant {Object.<string, string>}
80
+ * @type {Record<string, string>}
81
81
  */
82
82
  const BLUETOOTH_STATE = Object.freeze({
83
83
  UNKNOWN: 'unknown',
@@ -35,7 +35,7 @@ const NOISE_PROTOCOL_NAME = 'Noise_XX_25519_ChaChaPoly_SHA256';
35
35
 
36
36
  /**
37
37
  * Noise handshake states
38
- * @constant {Object.<string, string>}
38
+ * @type {Record<string, string>}
39
39
  */
40
40
  const NOISE_HANDSHAKE_STATE = Object.freeze({
41
41
  INITIAL: 'initial',
@@ -7,7 +7,7 @@
7
7
 
8
8
  /**
9
9
  * Error codes organized by category
10
- * @constant {Object.<string, string>}
10
+ * @type {Record<string, string>}
11
11
  */
12
12
  const ERROR_CODE = Object.freeze({
13
13
  // Initialization errors (E0xx)
@@ -108,7 +108,7 @@ const ERROR_CODE = Object.freeze({
108
108
 
109
109
  /**
110
110
  * Error messages for each error code
111
- * @constant {Object.<string, string>}
111
+ * @type {Record<string, string>}
112
112
  */
113
113
  const ERROR_MESSAGES = Object.freeze({
114
114
  E001: 'Initialization failed',
@@ -7,7 +7,7 @@
7
7
 
8
8
  /**
9
9
  * Event names for the mesh network
10
- * @constant {Object.<string, string>}
10
+ * @type {Record<string, string>}
11
11
  */
12
12
  const EVENTS = Object.freeze({
13
13
  // Lifecycle events
@@ -115,7 +115,7 @@ const MESH_CONFIG = Object.freeze({
115
115
 
116
116
  /**
117
117
  * Connection states
118
- * @constant {Object.<string, string>}
118
+ * @type {Record<string, string>}
119
119
  */
120
120
  const CONNECTION_STATE = Object.freeze({
121
121
  DISCONNECTED: 'disconnected',
@@ -129,7 +129,7 @@ const CONNECTION_STATE = Object.freeze({
129
129
 
130
130
  /**
131
131
  * Service states
132
- * @constant {Object.<string, string>}
132
+ * @type {Record<string, string>}
133
133
  */
134
134
  const SERVICE_STATE = Object.freeze({
135
135
  UNINITIALIZED: 'uninitialized',
@@ -14,25 +14,36 @@ const QuickCryptoProvider = require('./providers/QuickCryptoProvider');
14
14
  const ExpoCryptoProvider = require('./providers/ExpoCryptoProvider');
15
15
  const TweetNaClProvider = require('./providers/TweetNaClProvider');
16
16
 
17
+ /** @type {import('./CryptoProvider')|null} Cached singleton provider */
18
+ let _cachedProvider = null;
19
+
17
20
  /**
18
21
  * Detects and returns the best available crypto provider.
22
+ * The result is cached as a singleton for subsequent calls.
19
23
  * @returns {import('./CryptoProvider')} Best available provider
20
24
  * @throws {Error} If no crypto provider is available
21
25
  */
22
26
  function detectProvider() {
27
+ if (_cachedProvider) {
28
+ return _cachedProvider;
29
+ }
30
+
23
31
  // 1. Native speed (react-native-quick-crypto)
24
32
  if (QuickCryptoProvider.isAvailable()) {
25
- return new QuickCryptoProvider();
33
+ _cachedProvider = new QuickCryptoProvider();
34
+ return _cachedProvider;
26
35
  }
27
36
 
28
37
  // 2. Expo (expo-crypto + tweetnacl)
29
38
  if (ExpoCryptoProvider.isAvailable()) {
30
- return new ExpoCryptoProvider();
39
+ _cachedProvider = new ExpoCryptoProvider();
40
+ return _cachedProvider;
31
41
  }
32
42
 
33
43
  // 3. Universal (tweetnacl)
34
44
  if (TweetNaClProvider.isAvailable()) {
35
- return new TweetNaClProvider();
45
+ _cachedProvider = new TweetNaClProvider();
46
+ return _cachedProvider;
36
47
  }
37
48
 
38
49
  throw new Error(
@@ -53,7 +64,9 @@ function createProvider(config) {
53
64
  return detectProvider();
54
65
  }
55
66
 
67
+ // @ts-ignore
56
68
  if (typeof config === 'object' && typeof config.generateKeyPair === 'function') {
69
+ // @ts-ignore
57
70
  return config; // Already a provider instance
58
71
  }
59
72
 
@@ -37,53 +37,53 @@ class CryptoProvider {
37
37
 
38
38
  /**
39
39
  * Computes X25519 shared secret
40
- * @param {Uint8Array} secretKey - Our secret key (32 bytes)
41
- * @param {Uint8Array} publicKey - Their public key (32 bytes)
40
+ * @param {Uint8Array} _secretKey - Our secret key (32 bytes)
41
+ * @param {Uint8Array} _publicKey - Their public key (32 bytes)
42
42
  * @returns {Uint8Array} Shared secret (32 bytes)
43
43
  */
44
- sharedSecret(_secretKey, _publicKey) {
44
+ sharedSecret(/** @type {any} */ _secretKey, _publicKey) {
45
45
  throw new Error('CryptoProvider.sharedSecret() must be implemented');
46
46
  }
47
47
 
48
48
  /**
49
49
  * AEAD encrypt (XSalsa20-Poly1305 or ChaCha20-Poly1305)
50
- * @param {Uint8Array} key - Encryption key (32 bytes)
51
- * @param {Uint8Array} nonce - Nonce (24 bytes for XSalsa20, 12 for ChaCha20)
52
- * @param {Uint8Array} plaintext - Data to encrypt
53
- * @param {Uint8Array} [ad] - Additional authenticated data (optional)
50
+ * @param {Uint8Array} _key - Encryption key (32 bytes)
51
+ * @param {Uint8Array} _nonce - Nonce (24 bytes for XSalsa20, 12 for ChaCha20)
52
+ * @param {Uint8Array} _plaintext - Data to encrypt
53
+ * @param {Uint8Array} [_ad] - Additional authenticated data (optional)
54
54
  * @returns {Uint8Array} Ciphertext with authentication tag
55
55
  */
56
- encrypt(_key, _nonce, _plaintext, _ad) {
56
+ encrypt(/** @type {any} */ _key, _nonce, _plaintext, _ad) {
57
57
  throw new Error('CryptoProvider.encrypt() must be implemented');
58
58
  }
59
59
 
60
60
  /**
61
61
  * AEAD decrypt
62
- * @param {Uint8Array} key - Encryption key (32 bytes)
63
- * @param {Uint8Array} nonce - Nonce
64
- * @param {Uint8Array} ciphertext - Ciphertext with auth tag
65
- * @param {Uint8Array} [ad] - Additional authenticated data (optional)
62
+ * @param {Uint8Array} _key - Encryption key (32 bytes)
63
+ * @param {Uint8Array} _nonce - Nonce
64
+ * @param {Uint8Array} _ciphertext - Ciphertext with auth tag
65
+ * @param {Uint8Array} [_ad] - Additional authenticated data (optional)
66
66
  * @returns {Uint8Array|null} Plaintext or null if authentication fails
67
67
  */
68
- decrypt(_key, _nonce, _ciphertext, _ad) {
68
+ decrypt(/** @type {any} */ _key, _nonce, _ciphertext, _ad) {
69
69
  throw new Error('CryptoProvider.decrypt() must be implemented');
70
70
  }
71
71
 
72
72
  /**
73
73
  * Computes SHA-256 hash
74
- * @param {Uint8Array} data - Data to hash
74
+ * @param {Uint8Array} _data - Data to hash
75
75
  * @returns {Uint8Array} Hash (32 bytes)
76
76
  */
77
- hash(_data) {
77
+ hash(/** @type {any} */ _data) {
78
78
  throw new Error('CryptoProvider.hash() must be implemented');
79
79
  }
80
80
 
81
81
  /**
82
82
  * Generates cryptographically secure random bytes
83
- * @param {number} length - Number of bytes
83
+ * @param {number} _length - Number of bytes
84
84
  * @returns {Uint8Array} Random bytes
85
85
  */
86
- randomBytes(_length) {
86
+ randomBytes(/** @type {any} */ _length) {
87
87
  throw new Error('CryptoProvider.randomBytes() must be implemented');
88
88
  }
89
89
 
@@ -23,8 +23,10 @@ const CryptoProvider = require('../CryptoProvider');
23
23
  class ExpoCryptoProvider extends CryptoProvider {
24
24
  constructor(options = {}) {
25
25
  super();
26
- this._expoCrypto = options.expoCrypto || null;
27
- this._nacl = options.nacl || null;
26
+ /** @type {any} */
27
+ const opts = options;
28
+ this._expoCrypto = opts.expoCrypto || null;
29
+ this._nacl = opts.nacl || null;
28
30
  }
29
31
 
30
32
  get name() {
@@ -34,6 +36,7 @@ class ExpoCryptoProvider extends CryptoProvider {
34
36
  _getExpoCrypto() {
35
37
  if (!this._expoCrypto) {
36
38
  try {
39
+ // @ts-ignore
37
40
  this._expoCrypto = require('expo-crypto');
38
41
  } catch (e) {
39
42
  throw new Error('expo-crypto is required. Install: npx expo install expo-crypto');
@@ -45,6 +48,7 @@ class ExpoCryptoProvider extends CryptoProvider {
45
48
  _getNacl() {
46
49
  if (!this._nacl) {
47
50
  try {
51
+ // @ts-ignore
48
52
  this._nacl = require('tweetnacl');
49
53
  } catch (e) {
50
54
  throw new Error('tweetnacl is required with ExpoCryptoProvider. Install: npm install tweetnacl');
@@ -61,13 +65,13 @@ class ExpoCryptoProvider extends CryptoProvider {
61
65
  }
62
66
 
63
67
  /** @inheritdoc */
64
- sharedSecret(secretKey, publicKey) {
68
+ sharedSecret(/** @type {any} */ secretKey, /** @type {any} */ publicKey) {
65
69
  const nacl = this._getNacl();
66
70
  return nacl.box.before(publicKey, secretKey);
67
71
  }
68
72
 
69
73
  /** @inheritdoc */
70
- encrypt(key, nonce, plaintext, _ad) {
74
+ encrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ plaintext, /** @type {any} */ _ad) {
71
75
  const nacl = this._getNacl();
72
76
 
73
77
  // Ensure 24-byte nonce (pad short nonces with zeros)
@@ -81,7 +85,7 @@ class ExpoCryptoProvider extends CryptoProvider {
81
85
  }
82
86
 
83
87
  /** @inheritdoc */
84
- decrypt(key, nonce, ciphertext, _ad) {
88
+ decrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ ciphertext, /** @type {any} */ _ad) {
85
89
  const nacl = this._getNacl();
86
90
 
87
91
  // Ensure 24-byte nonce (pad short nonces with zeros)
@@ -95,17 +99,18 @@ class ExpoCryptoProvider extends CryptoProvider {
95
99
  }
96
100
 
97
101
  /** @inheritdoc */
98
- hash(data) {
102
+ hash(/** @type {any} */ data) {
99
103
  // expo-crypto's digestStringAsync is async — for sync compat, use tweetnacl
100
104
  const nacl = this._getNacl();
101
- return nacl.hash(data).slice(0, 32);
105
+ return nacl.hash(data).subarray(0, 32);
102
106
  }
103
107
 
104
108
  /** @inheritdoc */
105
- randomBytes(length) {
109
+ randomBytes(/** @type {any} */ length) {
106
110
  const expoCrypto = this._getExpoCrypto();
107
111
  if (expoCrypto.getRandomBytes) {
108
- return new Uint8Array(expoCrypto.getRandomBytes(length));
112
+ const bytes = expoCrypto.getRandomBytes(length);
113
+ return bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
109
114
  }
110
115
  // Fallback to tweetnacl
111
116
  const nacl = this._getNacl();
@@ -114,6 +119,7 @@ class ExpoCryptoProvider extends CryptoProvider {
114
119
 
115
120
  static isAvailable() {
116
121
  try {
122
+ // @ts-ignore
117
123
  require('expo-crypto');
118
124
  return true;
119
125
  } catch (e) {
@@ -10,6 +10,11 @@
10
10
 
11
11
  const CryptoProvider = require('../CryptoProvider');
12
12
 
13
+ /** DER header for PKCS8 private key wrapping (X25519) */
14
+ const PKCS8_HEADER = Buffer.from('302e020100300506032b656e04220420', 'hex');
15
+ /** DER header for SPKI public key wrapping (X25519) */
16
+ const SPKI_HEADER = Buffer.from('302a300506032b656e032100', 'hex');
17
+
13
18
  /**
14
19
  * Crypto provider using react-native-quick-crypto.
15
20
  * Provides native-speed crypto on React Native (JSI binding).
@@ -20,7 +25,10 @@ const CryptoProvider = require('../CryptoProvider');
20
25
  class QuickCryptoProvider extends CryptoProvider {
21
26
  constructor(options = {}) {
22
27
  super();
23
- this._crypto = options.crypto || null;
28
+ /** @type {any} */
29
+ const opts = options;
30
+ this._crypto = opts.crypto || null;
31
+ this._nacl = null;
24
32
  }
25
33
 
26
34
  get name() {
@@ -30,6 +38,7 @@ class QuickCryptoProvider extends CryptoProvider {
30
38
  _getCrypto() {
31
39
  if (!this._crypto) {
32
40
  try {
41
+ // @ts-ignore
33
42
  this._crypto = require('react-native-quick-crypto');
34
43
  } catch (e) {
35
44
  throw new Error(
@@ -51,11 +60,11 @@ class QuickCryptoProvider extends CryptoProvider {
51
60
  }
52
61
 
53
62
  /** @inheritdoc */
54
- sharedSecret(secretKey, publicKey) {
63
+ sharedSecret(/** @type {any} */ secretKey, /** @type {any} */ publicKey) {
55
64
  const crypto = this._getCrypto();
56
65
  const privKey = crypto.createPrivateKey({
57
66
  key: Buffer.concat([
58
- Buffer.from('302e020100300506032b656e04220420', 'hex'),
67
+ PKCS8_HEADER,
59
68
  Buffer.from(secretKey)
60
69
  ]),
61
70
  format: 'der',
@@ -63,7 +72,7 @@ class QuickCryptoProvider extends CryptoProvider {
63
72
  });
64
73
  const pubKey = crypto.createPublicKey({
65
74
  key: Buffer.concat([
66
- Buffer.from('302a300506032b656e032100', 'hex'),
75
+ SPKI_HEADER,
67
76
  Buffer.from(publicKey)
68
77
  ]),
69
78
  format: 'der',
@@ -73,11 +82,30 @@ class QuickCryptoProvider extends CryptoProvider {
73
82
  return new Uint8Array(shared);
74
83
  }
75
84
 
85
+ /**
86
+ * Lazily loads tweetnacl (cached)
87
+ * @returns {any} nacl module
88
+ * @private
89
+ */
90
+ _getNacl() {
91
+ if (!this._nacl) {
92
+ try {
93
+ // @ts-ignore
94
+ this._nacl = require('tweetnacl');
95
+ } catch (e) {
96
+ throw new Error(
97
+ 'tweetnacl is required for QuickCryptoProvider encrypt/decrypt/hash. Install: npm install tweetnacl'
98
+ );
99
+ }
100
+ }
101
+ return this._nacl;
102
+ }
103
+
76
104
  /** @inheritdoc */
77
- encrypt(key, nonce, plaintext, _ad) {
105
+ encrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ plaintext, /** @type {any} */ _ad) {
78
106
  // Use tweetnacl for encryption to ensure cross-provider compatibility
79
107
  // QuickCrypto's advantage is in fast native key generation (X25519), not AEAD
80
- const nacl = require('tweetnacl');
108
+ const nacl = this._getNacl();
81
109
 
82
110
  // Ensure 24-byte nonce for XSalsa20-Poly1305
83
111
  let fullNonce = nonce;
@@ -90,8 +118,8 @@ class QuickCryptoProvider extends CryptoProvider {
90
118
  }
91
119
 
92
120
  /** @inheritdoc */
93
- decrypt(key, nonce, ciphertext, _ad) {
94
- const nacl = require('tweetnacl');
121
+ decrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ ciphertext, /** @type {any} */ _ad) {
122
+ const nacl = this._getNacl();
95
123
 
96
124
  // Ensure 24-byte nonce for XSalsa20-Poly1305
97
125
  let fullNonce = nonce;
@@ -108,21 +136,22 @@ class QuickCryptoProvider extends CryptoProvider {
108
136
  }
109
137
 
110
138
  /** @inheritdoc */
111
- hash(data) {
139
+ hash(/** @type {any} */ data) {
112
140
  // Use SHA-512 truncated to 32 bytes for cross-provider compatibility
113
- const nacl = require('tweetnacl');
141
+ const nacl = this._getNacl();
114
142
  const full = nacl.hash(data); // SHA-512
115
- return full.slice(0, 32);
143
+ return full.subarray(0, 32);
116
144
  }
117
145
 
118
146
  /** @inheritdoc */
119
- randomBytes(length) {
147
+ randomBytes(/** @type {any} */ length) {
120
148
  const crypto = this._getCrypto();
121
149
  return new Uint8Array(crypto.randomBytes(length));
122
150
  }
123
151
 
124
152
  static isAvailable() {
125
153
  try {
154
+ // @ts-ignore
126
155
  require('react-native-quick-crypto');
127
156
  return true;
128
157
  } catch (e) {
@@ -20,7 +20,7 @@ const CryptoProvider = require('../CryptoProvider');
20
20
  class TweetNaClProvider extends CryptoProvider {
21
21
  /**
22
22
  * @param {Object} [options={}]
23
- * @param {Object} [options.nacl] - Injected tweetnacl instance (for testing)
23
+ * @param {any} [options.nacl] - Injected tweetnacl instance (for testing)
24
24
  */
25
25
  constructor(options = {}) {
26
26
  super();
@@ -33,12 +33,13 @@ class TweetNaClProvider extends CryptoProvider {
33
33
 
34
34
  /**
35
35
  * Lazily loads tweetnacl
36
- * @returns {Object} nacl module
36
+ * @returns {any} nacl module
37
37
  * @private
38
38
  */
39
39
  _getNacl() {
40
40
  if (!this._nacl) {
41
41
  try {
42
+ // @ts-ignore
42
43
  this._nacl = require('tweetnacl');
43
44
  } catch (e) {
44
45
  throw new Error(
@@ -57,13 +58,13 @@ class TweetNaClProvider extends CryptoProvider {
57
58
  }
58
59
 
59
60
  /** @inheritdoc */
60
- sharedSecret(secretKey, publicKey) {
61
+ sharedSecret(/** @type {any} */ secretKey, /** @type {any} */ publicKey) {
61
62
  const nacl = this._getNacl();
62
63
  return nacl.box.before(publicKey, secretKey);
63
64
  }
64
65
 
65
66
  /** @inheritdoc */
66
- encrypt(key, nonce, plaintext, _ad) {
67
+ encrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ plaintext, /** @type {any} */ _ad) {
67
68
  const nacl = this._getNacl();
68
69
  // tweetnacl uses XSalsa20-Poly1305 with 24-byte nonce
69
70
  // nacl.secretbox includes authentication
@@ -79,7 +80,7 @@ class TweetNaClProvider extends CryptoProvider {
79
80
  }
80
81
 
81
82
  /** @inheritdoc */
82
- decrypt(key, nonce, ciphertext, _ad) {
83
+ decrypt(/** @type {any} */ key, /** @type {any} */ nonce, /** @type {any} */ ciphertext, /** @type {any} */ _ad) {
83
84
  const nacl = this._getNacl();
84
85
 
85
86
  // Ensure 24-byte nonce (pad short nonces with zeros)
@@ -94,15 +95,15 @@ class TweetNaClProvider extends CryptoProvider {
94
95
  }
95
96
 
96
97
  /** @inheritdoc */
97
- hash(data) {
98
+ hash(/** @type {any} */ data) {
98
99
  const nacl = this._getNacl();
99
100
  // tweetnacl provides SHA-512; we return first 32 bytes for SHA-256 compatibility
100
101
  const full = nacl.hash(data);
101
- return full.slice(0, 32);
102
+ return full.subarray(0, 32);
102
103
  }
103
104
 
104
105
  /** @inheritdoc */
105
- randomBytes(length) {
106
+ randomBytes(/** @type {any} */ length) {
106
107
  const nacl = this._getNacl();
107
108
  return nacl.randomBytes(length);
108
109
  }
@@ -113,6 +114,7 @@ class TweetNaClProvider extends CryptoProvider {
113
114
  */
114
115
  static isAvailable() {
115
116
  try {
117
+ // @ts-ignore
116
118
  require('tweetnacl');
117
119
  return true;
118
120
  } catch (e) {
@@ -32,7 +32,7 @@ class AudioError extends MeshError {
32
32
  * @returns {AudioError}
33
33
  */
34
34
  static fromCode(code, details = null) {
35
- const message = ERROR_MESSAGES[code] || 'Audio operation failed';
35
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || 'Audio operation failed';
36
36
  return new AudioError(message, code, details);
37
37
  }
38
38
 
@@ -73,6 +73,7 @@ class AudioError extends MeshError {
73
73
  return new AudioError(
74
74
  `Audio session failed with peer ${peerId}`,
75
75
  'EA04',
76
+ // @ts-ignore
76
77
  { peerId, ...details }
77
78
  );
78
79
  }
@@ -40,7 +40,7 @@ class ConnectionError extends MeshError {
40
40
  * @returns {ConnectionError} New ConnectionError instance
41
41
  */
42
42
  static fromCode(code, peerId = null, details = null) {
43
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E200;
43
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E200;
44
44
  return new ConnectionError(message, code, peerId, details);
45
45
  }
46
46
 
@@ -96,7 +96,7 @@ class ConnectionError extends MeshError {
96
96
 
97
97
  /**
98
98
  * Converts error to a JSON-serializable object
99
- * @returns {Object} JSON representation of the error
99
+ * @returns {any} JSON representation of the error
100
100
  */
101
101
  toJSON() {
102
102
  return {
@@ -32,7 +32,7 @@ class CryptoError extends MeshError {
32
32
  * @returns {CryptoError} New CryptoError instance
33
33
  */
34
34
  static fromCode(code, details = null) {
35
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E400;
35
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E400;
36
36
  return new CryptoError(message, code, details);
37
37
  }
38
38
 
@@ -48,7 +48,7 @@ class HandshakeError extends MeshError {
48
48
  * @returns {HandshakeError} New HandshakeError instance
49
49
  */
50
50
  static fromCode(code, peerId = null, step = null, details = null) {
51
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E300;
51
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E300;
52
52
  return new HandshakeError(message, code, peerId, step, details);
53
53
  }
54
54
 
@@ -108,7 +108,7 @@ class HandshakeError extends MeshError {
108
108
 
109
109
  /**
110
110
  * Converts error to a JSON-serializable object
111
- * @returns {Object} JSON representation of the error
111
+ * @returns {any} JSON representation of the error
112
112
  */
113
113
  toJSON() {
114
114
  return {
@@ -37,7 +37,7 @@ class MeshError extends Error {
37
37
 
38
38
  /**
39
39
  * Additional error details
40
- * @type {Object|null}
40
+ * @type {any}
41
41
  */
42
42
  this.details = details;
43
43
 
@@ -60,7 +60,7 @@ class MeshError extends Error {
60
60
  * @returns {MeshError} New MeshError instance
61
61
  */
62
62
  static fromCode(code, details = null) {
63
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E900;
63
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E900;
64
64
  return new MeshError(message, code, details);
65
65
  }
66
66
 
@@ -69,12 +69,12 @@ class MeshError extends Error {
69
69
  * @returns {string} Error type name
70
70
  */
71
71
  getTypeName() {
72
- return ERROR_CODE[this.code] || 'UNKNOWN_ERROR';
72
+ return /** @type {Record<string, string>} */ (ERROR_CODE)[this.code] || 'UNKNOWN_ERROR';
73
73
  }
74
74
 
75
75
  /**
76
76
  * Converts error to a JSON-serializable object
77
- * @returns {Object} JSON representation of the error
77
+ * @returns {any} JSON representation of the error
78
78
  */
79
79
  toJSON() {
80
80
  return {
@@ -40,7 +40,7 @@ class MessageError extends MeshError {
40
40
  * @returns {MessageError} New MessageError instance
41
41
  */
42
42
  static fromCode(code, messageId = null, details = null) {
43
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E500;
43
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E500;
44
44
  return new MessageError(message, code, messageId, details);
45
45
  }
46
46
 
@@ -116,7 +116,7 @@ class MessageError extends MeshError {
116
116
 
117
117
  /**
118
118
  * Converts error to a JSON-serializable object
119
- * @returns {Object} JSON representation of the error
119
+ * @returns {any} JSON representation of the error
120
120
  */
121
121
  toJSON() {
122
122
  return {
@@ -87,7 +87,7 @@ class ValidationError extends MeshError {
87
87
  * @returns {ValidationError} New ValidationError instance
88
88
  */
89
89
  static fromCode(code, field = null, value = undefined, details = null) {
90
- const message = ERROR_MESSAGES[code] || ERROR_MESSAGES.E800;
90
+ const message = /** @type {Record<string, string>} */ (ERROR_MESSAGES)[code] || /** @type {Record<string, string>} */ (ERROR_MESSAGES).E800;
91
91
  return new ValidationError(message, code, field, value, details);
92
92
  }
93
93
 
@@ -127,7 +127,7 @@ class ValidationError extends MeshError {
127
127
  * Creates an out of range error
128
128
  * @param {string} field - Name of the field
129
129
  * @param {*} value - The invalid value
130
- * @param {Object} range - Expected range { min, max }
130
+ * @param {any} range - Expected range { min, max }
131
131
  * @returns {ValidationError} New ValidationError instance
132
132
  */
133
133
  static outOfRange(field, value, range) {
@@ -136,7 +136,7 @@ class ValidationError extends MeshError {
136
136
 
137
137
  /**
138
138
  * Converts error to a JSON-serializable object
139
- * @returns {Object} JSON representation of the error
139
+ * @returns {any} JSON representation of the error
140
140
  */
141
141
  toJSON() {
142
142
  return {