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.
- package/package.json +9 -2
- package/src/MeshNetwork.js +48 -46
- package/src/constants/audio.js +4 -4
- package/src/constants/ble.js +1 -1
- package/src/constants/crypto.js +1 -1
- package/src/constants/errors.js +2 -2
- package/src/constants/events.js +1 -1
- package/src/constants/protocol.js +2 -2
- package/src/crypto/AutoCrypto.js +2 -0
- package/src/crypto/CryptoProvider.js +17 -17
- package/src/crypto/providers/ExpoCryptoProvider.js +12 -7
- package/src/crypto/providers/QuickCryptoProvider.js +50 -15
- package/src/crypto/providers/TweetNaClProvider.js +9 -7
- package/src/errors/AudioError.js +2 -1
- package/src/errors/ConnectionError.js +2 -2
- package/src/errors/CryptoError.js +1 -1
- package/src/errors/HandshakeError.js +2 -2
- package/src/errors/MeshError.js +4 -4
- package/src/errors/MessageError.js +2 -2
- package/src/errors/ValidationError.js +3 -3
- package/src/expo/withBLEMesh.js +10 -10
- package/src/hooks/AppStateManager.js +10 -4
- package/src/hooks/useMesh.js +7 -7
- package/src/hooks/useMessages.js +13 -12
- package/src/hooks/usePeers.js +10 -9
- package/src/index.js +2 -2
- package/src/mesh/dedup/BloomFilter.js +1 -0
- package/src/mesh/dedup/DedupManager.js +4 -7
- package/src/mesh/dedup/MessageCache.js +3 -0
- package/src/mesh/fragment/Assembler.js +5 -4
- package/src/mesh/fragment/Fragmenter.js +2 -2
- package/src/mesh/monitor/ConnectionQuality.js +17 -8
- package/src/mesh/monitor/NetworkMonitor.js +22 -15
- package/src/mesh/peer/Peer.js +4 -9
- package/src/mesh/peer/PeerDiscovery.js +18 -19
- package/src/mesh/peer/PeerManager.js +14 -14
- package/src/mesh/router/MessageRouter.js +15 -15
- package/src/mesh/router/PathFinder.js +10 -13
- package/src/mesh/router/RouteTable.js +8 -7
- package/src/mesh/store/StoreAndForwardManager.js +20 -23
- package/src/protocol/message.js +5 -13
- package/src/protocol/serializer.js +4 -4
- package/src/protocol/validator.js +7 -6
- package/src/service/BatteryOptimizer.js +18 -17
- package/src/service/EmergencyManager.js +19 -26
- package/src/service/HandshakeManager.js +100 -2
- package/src/service/MeshService.js +106 -22
- package/src/service/SessionManager.js +38 -3
- package/src/service/audio/AudioManager.js +80 -38
- package/src/service/audio/buffer/FrameBuffer.js +7 -8
- package/src/service/audio/buffer/JitterBuffer.js +1 -1
- package/src/service/audio/codec/LC3Codec.js +22 -20
- package/src/service/audio/codec/LC3Decoder.js +10 -10
- package/src/service/audio/codec/LC3Encoder.js +11 -9
- package/src/service/audio/session/AudioSession.js +14 -17
- package/src/service/audio/session/VoiceMessage.js +15 -22
- package/src/service/audio/transport/AudioFragmenter.js +17 -9
- package/src/service/audio/transport/AudioFramer.js +8 -12
- package/src/service/file/FileAssembler.js +4 -2
- package/src/service/file/FileChunker.js +1 -1
- package/src/service/file/FileManager.js +26 -20
- package/src/service/file/FileMessage.js +7 -12
- package/src/service/text/TextManager.js +55 -28
- package/src/service/text/broadcast/BroadcastManager.js +14 -17
- package/src/service/text/channel/Channel.js +10 -14
- package/src/service/text/channel/ChannelManager.js +10 -10
- package/src/service/text/message/TextMessage.js +12 -19
- package/src/service/text/message/TextSerializer.js +2 -2
- package/src/storage/AsyncStorageAdapter.js +17 -14
- package/src/storage/MemoryStorage.js +11 -8
- package/src/storage/MessageStore.js +22 -30
- package/src/storage/Storage.js +9 -9
- package/src/transport/BLETransport.js +16 -14
- package/src/transport/MockTransport.js +7 -2
- package/src/transport/MultiTransport.js +13 -6
- package/src/transport/Transport.js +9 -9
- package/src/transport/WiFiDirectTransport.js +25 -24
- package/src/transport/adapters/BLEAdapter.js +19 -19
- package/src/transport/adapters/NodeBLEAdapter.js +24 -23
- package/src/transport/adapters/RNBLEAdapter.js +19 -24
- package/src/utils/EventEmitter.js +17 -12
- package/src/utils/LRUCache.js +10 -4
- package/src/utils/RateLimiter.js +1 -1
- package/src/utils/compression.js +6 -8
- package/src/utils/encoding.js +8 -2
- package/src/utils/retry.js +11 -13
- package/src/utils/time.js +9 -4
- package/src/utils/validation.js +1 -1
package/src/utils/LRUCache.js
CHANGED
|
@@ -47,7 +47,7 @@ class LRUCache {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// Move to end (most recently used)
|
|
50
|
-
const value = this._cache.get(key);
|
|
50
|
+
const value = /** @type {V} */ (this._cache.get(key));
|
|
51
51
|
this._cache.delete(key);
|
|
52
52
|
this._cache.set(key, value);
|
|
53
53
|
|
|
@@ -67,7 +67,9 @@ class LRUCache {
|
|
|
67
67
|
} else if (this._cache.size >= this._maxSize) {
|
|
68
68
|
// Remove least recently used (first item)
|
|
69
69
|
const firstKey = this._cache.keys().next().value;
|
|
70
|
-
|
|
70
|
+
if (firstKey !== undefined) {
|
|
71
|
+
this._cache.delete(firstKey);
|
|
72
|
+
}
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
this._cache.set(key, value);
|
|
@@ -134,7 +136,7 @@ class LRUCache {
|
|
|
134
136
|
|
|
135
137
|
/**
|
|
136
138
|
* Returns all entries in the cache (most recent last)
|
|
137
|
-
* @returns {
|
|
139
|
+
* @returns {any[]} Array of [key, value] pairs
|
|
138
140
|
*/
|
|
139
141
|
entries() {
|
|
140
142
|
return Array.from(this._cache.entries());
|
|
@@ -194,7 +196,11 @@ class LRUCache {
|
|
|
194
196
|
// Evict oldest items if over new limit
|
|
195
197
|
while (this._cache.size > this._maxSize) {
|
|
196
198
|
const firstKey = this._cache.keys().next().value;
|
|
197
|
-
|
|
199
|
+
if (firstKey !== undefined) {
|
|
200
|
+
this._cache.delete(firstKey);
|
|
201
|
+
} else {
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
198
204
|
}
|
|
199
205
|
}
|
|
200
206
|
}
|
package/src/utils/RateLimiter.js
CHANGED
package/src/utils/compression.js
CHANGED
|
@@ -15,7 +15,7 @@ const { ValidationError, MeshError } = require('../errors');
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Default compression configuration
|
|
18
|
-
* @constant {
|
|
18
|
+
* @constant {any}
|
|
19
19
|
*/
|
|
20
20
|
const DEFAULT_CONFIG = Object.freeze({
|
|
21
21
|
/** Minimum payload size to compress (bytes) */
|
|
@@ -45,8 +45,8 @@ const DEFAULT_CONFIG = Object.freeze({
|
|
|
45
45
|
class MessageCompressor {
|
|
46
46
|
/**
|
|
47
47
|
* Creates a new MessageCompressor instance.
|
|
48
|
-
* @param {
|
|
49
|
-
|
|
48
|
+
* @param {any} [options={}] - Compression options
|
|
49
|
+
*
|
|
50
50
|
*/
|
|
51
51
|
constructor(options = {}) {
|
|
52
52
|
this._config = { ...DEFAULT_CONFIG, ...options };
|
|
@@ -89,11 +89,9 @@ class MessageCompressor {
|
|
|
89
89
|
this._stats.bytesOut += compressed.length;
|
|
90
90
|
return { data: compressed, compressed: true };
|
|
91
91
|
}
|
|
92
|
-
} catch (error) {
|
|
92
|
+
} catch (/** @type {any} */ error) {
|
|
93
93
|
// Log compression error at debug level for troubleshooting
|
|
94
|
-
|
|
95
|
-
console.debug('Compression failed, using uncompressed:', error.message);
|
|
96
|
-
}
|
|
94
|
+
// Compression failure is non-fatal — silently fall back to uncompressed
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
this._stats.bytesOut += payload.length;
|
|
@@ -132,7 +130,7 @@ class MessageCompressor {
|
|
|
132
130
|
|
|
133
131
|
/**
|
|
134
132
|
* Gets compression statistics.
|
|
135
|
-
* @returns {
|
|
133
|
+
* @returns {any} Statistics
|
|
136
134
|
*/
|
|
137
135
|
getStats() {
|
|
138
136
|
const ratio = this._stats.bytesIn > 0
|
package/src/utils/encoding.js
CHANGED
|
@@ -21,9 +21,12 @@ for (let i = 0; i < 256; i++) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Cached TextEncoder/TextDecoder singletons (avoid per-call allocation)
|
|
24
|
-
let _cachedEncoder = null;
|
|
25
|
-
let _cachedDecoder = null;
|
|
24
|
+
/** @type {any} */ let _cachedEncoder = null;
|
|
25
|
+
/** @type {any} */ let _cachedDecoder = null;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* @returns {any}
|
|
29
|
+
*/
|
|
27
30
|
function _getEncoder() {
|
|
28
31
|
if (!_cachedEncoder && typeof TextEncoder !== 'undefined') {
|
|
29
32
|
_cachedEncoder = new TextEncoder();
|
|
@@ -31,6 +34,9 @@ function _getEncoder() {
|
|
|
31
34
|
return _cachedEncoder;
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
/**
|
|
38
|
+
* @returns {any}
|
|
39
|
+
*/
|
|
34
40
|
function _getDecoder() {
|
|
35
41
|
if (!_cachedDecoder && typeof TextDecoder !== 'undefined') {
|
|
36
42
|
_cachedDecoder = new TextDecoder();
|
package/src/utils/retry.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Default retry options
|
|
10
|
-
* @constant {
|
|
10
|
+
* @constant {any}
|
|
11
11
|
*/
|
|
12
12
|
const DEFAULT_OPTIONS = {
|
|
13
13
|
maxRetries: 3,
|
|
@@ -21,7 +21,7 @@ const DEFAULT_OPTIONS = {
|
|
|
21
21
|
/**
|
|
22
22
|
* Calculates delay with optional jitter
|
|
23
23
|
* @param {number} attempt - Current attempt number (0-based)
|
|
24
|
-
* @param {
|
|
24
|
+
* @param {any} options - Retry options
|
|
25
25
|
* @returns {number} Delay in milliseconds
|
|
26
26
|
* @private
|
|
27
27
|
*/
|
|
@@ -46,13 +46,10 @@ function calculateDelay(attempt, options) {
|
|
|
46
46
|
* Retries an async function with exponential backoff
|
|
47
47
|
* @template T
|
|
48
48
|
* @param {function(): Promise<T>} fn - Async function to retry
|
|
49
|
-
* @param {
|
|
50
|
-
* @param {
|
|
51
|
-
* @param {number} [options.initialDelay=100] - Initial delay in milliseconds
|
|
52
|
-
* @param {number} [options.maxDelay=10000] - Maximum delay in milliseconds
|
|
53
|
-
* @param {number} [options.factor=2] - Exponential factor
|
|
54
|
-
* @param {boolean} [options.jitter=true] - Add randomness to delays
|
|
49
|
+
* @param {any} [options] - Retry options *
|
|
50
|
+
* @param {object} options
|
|
55
51
|
* @param {function(Error, number): boolean} [options.shouldRetry] - Predicate to determine if should retry
|
|
52
|
+
* @param {object} options
|
|
56
53
|
* @param {function(Error, number): void} [options.onRetry] - Callback on each retry
|
|
57
54
|
* @returns {Promise<T>} Result of the function
|
|
58
55
|
* @throws {Error} Last error if all retries fail
|
|
@@ -66,7 +63,7 @@ async function retry(fn, options = {}) {
|
|
|
66
63
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
67
64
|
try {
|
|
68
65
|
return await fn();
|
|
69
|
-
} catch (error) {
|
|
66
|
+
} catch (/** @type {any} */ error) {
|
|
70
67
|
lastError = error;
|
|
71
68
|
|
|
72
69
|
// Check if we should retry
|
|
@@ -94,11 +91,12 @@ async function retry(fn, options = {}) {
|
|
|
94
91
|
* Creates a retryable version of an async function
|
|
95
92
|
* @template T
|
|
96
93
|
* @param {function(...*): Promise<T>} fn - Async function to wrap
|
|
97
|
-
* @param {
|
|
94
|
+
* @param {any} [options] - Retry options
|
|
98
95
|
* @returns {function(...*): Promise<T>} Wrapped function with retry logic
|
|
99
96
|
*/
|
|
100
97
|
function retryable(fn, options = {}) {
|
|
101
98
|
return function retryableFn(...args) {
|
|
99
|
+
// @ts-ignore
|
|
102
100
|
return retry(() => fn.apply(this, args), options);
|
|
103
101
|
};
|
|
104
102
|
}
|
|
@@ -109,7 +107,7 @@ function retryable(fn, options = {}) {
|
|
|
109
107
|
* @returns {function(Error): boolean} Predicate function
|
|
110
108
|
*/
|
|
111
109
|
function retryOn(errorTypes) {
|
|
112
|
-
return (error) => {
|
|
110
|
+
return (/** @type {any} */ error) => {
|
|
113
111
|
return errorTypes.some(ErrorType => error instanceof ErrorType);
|
|
114
112
|
};
|
|
115
113
|
}
|
|
@@ -120,7 +118,7 @@ function retryOn(errorTypes) {
|
|
|
120
118
|
* @returns {function(Error): boolean} Predicate function
|
|
121
119
|
*/
|
|
122
120
|
function retryExcept(errorTypes) {
|
|
123
|
-
return (error) => {
|
|
121
|
+
return (/** @type {any} */ error) => {
|
|
124
122
|
return !errorTypes.some(ErrorType => error instanceof ErrorType);
|
|
125
123
|
};
|
|
126
124
|
}
|
|
@@ -131,7 +129,7 @@ function retryExcept(errorTypes) {
|
|
|
131
129
|
* @returns {function(Error): boolean} Predicate function
|
|
132
130
|
*/
|
|
133
131
|
function retryOnCodes(codes) {
|
|
134
|
-
return (error) => {
|
|
132
|
+
return (/** @type {any} */ error) => {
|
|
135
133
|
return error.code && codes.includes(error.code);
|
|
136
134
|
};
|
|
137
135
|
}
|
package/src/utils/time.js
CHANGED
|
@@ -23,8 +23,9 @@ function delay(ms) {
|
|
|
23
23
|
* @returns {Promise<T>} Promise that rejects on timeout
|
|
24
24
|
*/
|
|
25
25
|
function withTimeout(promise, ms, message = 'Operation timed out') {
|
|
26
|
-
let timeoutId;
|
|
26
|
+
/** @type {any} */ let timeoutId;
|
|
27
27
|
|
|
28
|
+
/** @type {Promise<T>} */
|
|
28
29
|
const timeoutPromise = new Promise((_, reject) => {
|
|
29
30
|
timeoutId = setTimeout(() => {
|
|
30
31
|
reject(new Error(message));
|
|
@@ -32,10 +33,10 @@ function withTimeout(promise, ms, message = 'Operation timed out') {
|
|
|
32
33
|
});
|
|
33
34
|
|
|
34
35
|
return Promise.race([
|
|
35
|
-
promise.then(result => {
|
|
36
|
+
promise.then((/** @type {T} */ result) => {
|
|
36
37
|
clearTimeout(timeoutId);
|
|
37
38
|
return result;
|
|
38
|
-
}).catch(error => {
|
|
39
|
+
}).catch((/** @type {any} */ error) => {
|
|
39
40
|
clearTimeout(timeoutId);
|
|
40
41
|
throw error;
|
|
41
42
|
}),
|
|
@@ -57,7 +58,9 @@ function now() {
|
|
|
57
58
|
* @returns {number} High-resolution timestamp
|
|
58
59
|
*/
|
|
59
60
|
function hrTime() {
|
|
61
|
+
// @ts-ignore - performance may be available in some environments
|
|
60
62
|
if (typeof performance !== 'undefined' && performance.now) {
|
|
63
|
+
// @ts-ignore
|
|
61
64
|
return performance.now();
|
|
62
65
|
}
|
|
63
66
|
return Date.now();
|
|
@@ -119,7 +122,7 @@ function formatDuration(ms) {
|
|
|
119
122
|
* @returns {function(...*): void} Debounced function
|
|
120
123
|
*/
|
|
121
124
|
function debounce(fn, waitMs) {
|
|
122
|
-
let timeoutId = null;
|
|
125
|
+
/** @type {any} */ let timeoutId = null;
|
|
123
126
|
|
|
124
127
|
return function debounced(...args) {
|
|
125
128
|
if (timeoutId !== null) {
|
|
@@ -128,6 +131,7 @@ function debounce(fn, waitMs) {
|
|
|
128
131
|
|
|
129
132
|
timeoutId = setTimeout(() => {
|
|
130
133
|
timeoutId = null;
|
|
134
|
+
// @ts-ignore
|
|
131
135
|
fn.apply(this, args);
|
|
132
136
|
}, waitMs);
|
|
133
137
|
};
|
|
@@ -148,6 +152,7 @@ function throttle(fn, intervalMs) {
|
|
|
148
152
|
|
|
149
153
|
if (currentTime - lastCall >= intervalMs) {
|
|
150
154
|
lastCall = currentTime;
|
|
155
|
+
// @ts-ignore
|
|
151
156
|
return fn.apply(this, args);
|
|
152
157
|
}
|
|
153
158
|
};
|
package/src/utils/validation.js
CHANGED
|
@@ -74,7 +74,7 @@ function validatePositiveInt(value, name) {
|
|
|
74
74
|
* Validates that a value is one of the allowed values
|
|
75
75
|
* @param {*} value - Value to validate
|
|
76
76
|
* @param {string} name - Name of the parameter for error messages
|
|
77
|
-
* @param {
|
|
77
|
+
* @param {any[]} allowed - Array of allowed values
|
|
78
78
|
* @throws {ValidationError} If value is not in allowed list
|
|
79
79
|
*/
|
|
80
80
|
function validateEnum(value, name, allowed) {
|