react-native-ble-mesh 2.1.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.
- package/package.json +1 -1
- 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 +12 -7
- 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 +2 -1
- 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 +18 -25
- 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 +18 -19
- 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 +22 -17
- package/src/transport/adapters/BLEAdapter.js +19 -19
- package/src/transport/adapters/NodeBLEAdapter.js +24 -23
- package/src/transport/adapters/RNBLEAdapter.js +14 -11
- package/src/utils/EventEmitter.js +9 -7
- package/src/utils/LRUCache.js +10 -4
- package/src/utils/RateLimiter.js +1 -1
- package/src/utils/compression.js +5 -5
- 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
|
@@ -21,7 +21,7 @@ const cachedDecoder = new TextDecoder();
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Text manager states
|
|
24
|
-
* @constant {
|
|
24
|
+
* @constant {any}
|
|
25
25
|
*/
|
|
26
26
|
const MANAGER_STATE = Object.freeze({
|
|
27
27
|
UNINITIALIZED: 'uninitialized',
|
|
@@ -40,34 +40,34 @@ const MANAGER_STATE = Object.freeze({
|
|
|
40
40
|
class TextManager extends EventEmitter {
|
|
41
41
|
/**
|
|
42
42
|
* Creates a new TextManager
|
|
43
|
-
* @param {
|
|
43
|
+
* @param {any} [options] - Manager options
|
|
44
44
|
*/
|
|
45
45
|
constructor(options = {}) {
|
|
46
46
|
super();
|
|
47
47
|
|
|
48
|
-
/** @private */
|
|
48
|
+
/** @type {string} @private */
|
|
49
49
|
this._state = MANAGER_STATE.UNINITIALIZED;
|
|
50
|
-
/** @private */
|
|
50
|
+
/** @type {any} @private */
|
|
51
51
|
this._meshService = null;
|
|
52
52
|
/** @private */
|
|
53
53
|
this._channelManager = new ChannelManager();
|
|
54
54
|
/** @private */
|
|
55
55
|
this._broadcastManager = new BroadcastManager(options.broadcast);
|
|
56
|
-
/** @private */
|
|
56
|
+
/** @type {string | null} @private */
|
|
57
57
|
this._senderId = null;
|
|
58
|
-
/** @private */
|
|
58
|
+
/** @type {number} @private */
|
|
59
59
|
this._messageCounter = 0;
|
|
60
|
-
/** @private */
|
|
60
|
+
/** @type {Set<string>} @private */
|
|
61
61
|
this._pendingReadReceipts = new Set();
|
|
62
|
-
/** @private */
|
|
62
|
+
/** @type {ReturnType<typeof setTimeout> | null} @private */
|
|
63
63
|
this._readReceiptBatchTimeout = null;
|
|
64
|
-
/** @private */
|
|
64
|
+
/** @type {number} @private */
|
|
65
65
|
this._readReceiptBatchDelayMs = options.readReceiptBatchDelayMs || 1000;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
69
69
|
* Initializes the text manager
|
|
70
|
-
* @param {
|
|
70
|
+
* @param {any} meshService - Mesh service instance
|
|
71
71
|
* @returns {Promise<void>}
|
|
72
72
|
*/
|
|
73
73
|
async initialize(meshService) {
|
|
@@ -89,7 +89,7 @@ class TextManager extends EventEmitter {
|
|
|
89
89
|
// Initialize broadcast manager
|
|
90
90
|
this._broadcastManager.initialize({
|
|
91
91
|
senderId: this._senderId,
|
|
92
|
-
sendCallback: (message) => this._sendBroadcastMessage(message)
|
|
92
|
+
sendCallback: (/** @type {any} */ message) => this._sendBroadcastMessage(message)
|
|
93
93
|
});
|
|
94
94
|
|
|
95
95
|
// Setup event forwarding
|
|
@@ -97,7 +97,7 @@ class TextManager extends EventEmitter {
|
|
|
97
97
|
|
|
98
98
|
this._setState(MANAGER_STATE.READY);
|
|
99
99
|
this.emit('initialized');
|
|
100
|
-
} catch (error) {
|
|
100
|
+
} catch (/** @type {any} */ error) {
|
|
101
101
|
this._setState(MANAGER_STATE.ERROR);
|
|
102
102
|
throw new MeshError(`Text manager initialization failed: ${error.message}`, ERROR_CODE.E001);
|
|
103
103
|
}
|
|
@@ -203,7 +203,7 @@ class TextManager extends EventEmitter {
|
|
|
203
203
|
/**
|
|
204
204
|
* Gets recent broadcasts
|
|
205
205
|
* @param {number} [limit] - Maximum number to return
|
|
206
|
-
* @returns {
|
|
206
|
+
* @returns {any[]}
|
|
207
207
|
*/
|
|
208
208
|
getRecentBroadcasts(limit) {
|
|
209
209
|
return this._broadcastManager.getRecentBroadcasts(limit);
|
|
@@ -215,6 +215,7 @@ class TextManager extends EventEmitter {
|
|
|
215
215
|
* Joins a channel
|
|
216
216
|
* @param {string} channelId - Channel ID
|
|
217
217
|
* @param {string} [password] - Optional password
|
|
218
|
+
* @returns {any}
|
|
218
219
|
*/
|
|
219
220
|
joinChannel(channelId, password) {
|
|
220
221
|
this._validateReady();
|
|
@@ -287,7 +288,7 @@ class TextManager extends EventEmitter {
|
|
|
287
288
|
|
|
288
289
|
/**
|
|
289
290
|
* Gets all joined channels
|
|
290
|
-
* @returns {
|
|
291
|
+
* @returns {any[]}
|
|
291
292
|
*/
|
|
292
293
|
getChannels() {
|
|
293
294
|
return this._channelManager.getChannels();
|
|
@@ -296,7 +297,7 @@ class TextManager extends EventEmitter {
|
|
|
296
297
|
/**
|
|
297
298
|
* Gets a specific channel
|
|
298
299
|
* @param {string} channelId - Channel ID
|
|
299
|
-
* @returns {
|
|
300
|
+
* @returns {any}
|
|
300
301
|
*/
|
|
301
302
|
getChannel(channelId) {
|
|
302
303
|
return this._channelManager.getChannel(channelId);
|
|
@@ -358,6 +359,7 @@ class TextManager extends EventEmitter {
|
|
|
358
359
|
// Extract channel ID from payload
|
|
359
360
|
this._handleChannelMessagePayload(peerId, payload);
|
|
360
361
|
break;
|
|
362
|
+
// @ts-ignore
|
|
361
363
|
case MESSAGE_TYPE.READ_RECEIPT:
|
|
362
364
|
this._handleReadReceipt(peerId, payload);
|
|
363
365
|
break;
|
|
@@ -379,20 +381,25 @@ class TextManager extends EventEmitter {
|
|
|
379
381
|
EVENTS.CHANNEL_MEMBER_JOINED,
|
|
380
382
|
EVENTS.CHANNEL_MEMBER_LEFT
|
|
381
383
|
];
|
|
382
|
-
channelEvents.forEach(event => {
|
|
383
|
-
this._channelManager.on(event, data => this.emit(event, data));
|
|
384
|
+
channelEvents.forEach((/** @type {any} */ event) => {
|
|
385
|
+
this._channelManager.on(event, (/** @type {any} */ data) => this.emit(event, data));
|
|
384
386
|
});
|
|
385
387
|
|
|
386
388
|
// Forward broadcast events
|
|
387
|
-
this._broadcastManager.on('broadcast-sent', data => {
|
|
389
|
+
this._broadcastManager.on('broadcast-sent', (/** @type {any} */ data) => {
|
|
388
390
|
this.emit(EVENTS.BROADCAST_SENT, data);
|
|
389
391
|
});
|
|
390
|
-
this._broadcastManager.on('broadcast-received', data => {
|
|
392
|
+
this._broadcastManager.on('broadcast-received', (/** @type {any} */ data) => {
|
|
391
393
|
this.emit(EVENTS.BROADCAST_RECEIVED, data);
|
|
392
394
|
});
|
|
393
395
|
}
|
|
394
396
|
|
|
395
|
-
/**
|
|
397
|
+
/**
|
|
398
|
+
* @param {string} peerId - Peer ID
|
|
399
|
+
* @param {number} type - Message type
|
|
400
|
+
* @param {Uint8Array} payload - Message payload
|
|
401
|
+
* @private
|
|
402
|
+
*/
|
|
396
403
|
async _sendMessage(peerId, type, payload) {
|
|
397
404
|
const data = new Uint8Array(1 + payload.length);
|
|
398
405
|
data[0] = type;
|
|
@@ -403,7 +410,10 @@ class TextManager extends EventEmitter {
|
|
|
403
410
|
}
|
|
404
411
|
}
|
|
405
412
|
|
|
406
|
-
/**
|
|
413
|
+
/**
|
|
414
|
+
* @param {any} message - Message to broadcast
|
|
415
|
+
* @private
|
|
416
|
+
*/
|
|
407
417
|
async _sendBroadcastMessage(message) {
|
|
408
418
|
const serialized = message.serialize();
|
|
409
419
|
const data = new Uint8Array(1 + serialized.length);
|
|
@@ -423,7 +433,11 @@ class TextManager extends EventEmitter {
|
|
|
423
433
|
}
|
|
424
434
|
}
|
|
425
435
|
|
|
426
|
-
/**
|
|
436
|
+
/**
|
|
437
|
+
* @param {string} peerId - Peer ID
|
|
438
|
+
* @param {Uint8Array} payload - Message payload
|
|
439
|
+
* @private
|
|
440
|
+
*/
|
|
427
441
|
_handleChannelMessagePayload(peerId, payload) {
|
|
428
442
|
// First byte is channel ID length
|
|
429
443
|
const channelIdLength = payload[0];
|
|
@@ -433,9 +447,14 @@ class TextManager extends EventEmitter {
|
|
|
433
447
|
this.handleChannelMessage(peerId, channelId, messagePayload);
|
|
434
448
|
}
|
|
435
449
|
|
|
436
|
-
/**
|
|
450
|
+
/**
|
|
451
|
+
* @param {string} peerId - Peer ID
|
|
452
|
+
* @param {Uint8Array} payload - Message payload
|
|
453
|
+
* @private
|
|
454
|
+
*/
|
|
437
455
|
_handleReadReceipt(peerId, payload) {
|
|
438
456
|
// Parse read receipt payload
|
|
457
|
+
/** @type {string[]} */
|
|
439
458
|
const messageIds = [];
|
|
440
459
|
let offset = 0;
|
|
441
460
|
|
|
@@ -464,7 +483,7 @@ class TextManager extends EventEmitter {
|
|
|
464
483
|
this._pendingReadReceipts.clear();
|
|
465
484
|
|
|
466
485
|
// Pre-calculate total size and allocate once
|
|
467
|
-
const encodedIds = messageIds.map(id => cachedEncoder.encode(id));
|
|
486
|
+
const encodedIds = messageIds.map((/** @type {string} */ id) => cachedEncoder.encode(id));
|
|
468
487
|
let totalLength = 0;
|
|
469
488
|
for (let i = 0; i < encodedIds.length; i++) {
|
|
470
489
|
totalLength += 1 + encodedIds[i].length;
|
|
@@ -489,16 +508,23 @@ class TextManager extends EventEmitter {
|
|
|
489
508
|
}
|
|
490
509
|
}
|
|
491
510
|
|
|
492
|
-
/**
|
|
511
|
+
/**
|
|
512
|
+
* @param {string} newState - New state
|
|
513
|
+
* @private
|
|
514
|
+
*/
|
|
493
515
|
_setState(newState) {
|
|
494
516
|
this._state = newState;
|
|
495
517
|
}
|
|
496
518
|
|
|
497
|
-
/**
|
|
519
|
+
/**
|
|
520
|
+
* @param {any} publicKey - Public key
|
|
521
|
+
* @returns {string}
|
|
522
|
+
* @private
|
|
523
|
+
*/
|
|
498
524
|
_publicKeyToId(publicKey) {
|
|
499
525
|
if (publicKey instanceof Uint8Array) {
|
|
500
526
|
return Array.from(publicKey.slice(0, 8))
|
|
501
|
-
.map(b => b.toString(16).padStart(2, '0'))
|
|
527
|
+
.map((/** @type {number} */ b) => b.toString(16).padStart(2, '0'))
|
|
502
528
|
.join('');
|
|
503
529
|
}
|
|
504
530
|
return String(publicKey).slice(0, 16);
|
|
@@ -514,7 +540,7 @@ class TextManager extends EventEmitter {
|
|
|
514
540
|
|
|
515
541
|
/**
|
|
516
542
|
* Returns statistics
|
|
517
|
-
* @returns {
|
|
543
|
+
* @returns {any}
|
|
518
544
|
*/
|
|
519
545
|
getStats() {
|
|
520
546
|
return {
|
|
@@ -525,6 +551,7 @@ class TextManager extends EventEmitter {
|
|
|
525
551
|
}
|
|
526
552
|
}
|
|
527
553
|
|
|
554
|
+
/** @type {any} */
|
|
528
555
|
TextManager.STATE = MANAGER_STATE;
|
|
529
556
|
|
|
530
557
|
module.exports = TextManager;
|
|
@@ -10,7 +10,7 @@ const TextMessage = require('../message/TextMessage');
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Broadcast configuration
|
|
13
|
-
* @constant {
|
|
13
|
+
* @constant {any}
|
|
14
14
|
*/
|
|
15
15
|
const BROADCAST_CONFIG = Object.freeze({
|
|
16
16
|
MAX_MESSAGE_SIZE: 1000,
|
|
@@ -26,26 +26,24 @@ const BROADCAST_CONFIG = Object.freeze({
|
|
|
26
26
|
class BroadcastManager extends EventEmitter {
|
|
27
27
|
/**
|
|
28
28
|
* Creates a new BroadcastManager
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {number} [options.maxRecentBroadcasts] - Max broadcasts to keep
|
|
31
|
-
* @param {number} [options.dedupWindowMs] - Deduplication window
|
|
29
|
+
* @param {any} [options] - Manager options
|
|
32
30
|
*/
|
|
33
31
|
constructor(options = {}) {
|
|
34
32
|
super();
|
|
35
33
|
|
|
36
|
-
/** @private */
|
|
34
|
+
/** @type {number} @private */
|
|
37
35
|
this._maxRecentBroadcasts = options.maxRecentBroadcasts || BROADCAST_CONFIG.MAX_RECENT_BROADCASTS;
|
|
38
|
-
/** @private */
|
|
36
|
+
/** @type {number} @private */
|
|
39
37
|
this._dedupWindowMs = options.dedupWindowMs || BROADCAST_CONFIG.DEDUP_WINDOW_MS;
|
|
40
|
-
/** @private */
|
|
38
|
+
/** @type {any[]} @private */
|
|
41
39
|
this._recentBroadcasts = [];
|
|
42
|
-
/** @private */
|
|
40
|
+
/** @type {Map<string, number>} @private */
|
|
43
41
|
this._seenMessageIds = new Map(); // messageId -> timestamp
|
|
44
|
-
/** @private */
|
|
42
|
+
/** @type {string | null} @private */
|
|
45
43
|
this._senderId = null;
|
|
46
|
-
/** @private */
|
|
44
|
+
/** @type {Function | null} @private */
|
|
47
45
|
this._sendCallback = null;
|
|
48
|
-
/** @private */
|
|
46
|
+
/** @type {ReturnType<typeof setInterval> | null} @private */
|
|
49
47
|
this._cleanupTimer = null;
|
|
50
48
|
|
|
51
49
|
// Auto-cleanup every 5 minutes
|
|
@@ -60,9 +58,7 @@ class BroadcastManager extends EventEmitter {
|
|
|
60
58
|
|
|
61
59
|
/**
|
|
62
60
|
* Initializes the broadcast manager
|
|
63
|
-
* @param {
|
|
64
|
-
* @param {string} options.senderId - Local sender ID
|
|
65
|
-
* @param {Function} options.sendCallback - Callback to send broadcast
|
|
61
|
+
* @param {any} options - Init options
|
|
66
62
|
*/
|
|
67
63
|
initialize(options) {
|
|
68
64
|
this._senderId = options.senderId;
|
|
@@ -155,7 +151,7 @@ class BroadcastManager extends EventEmitter {
|
|
|
155
151
|
/**
|
|
156
152
|
* Gets recent broadcasts
|
|
157
153
|
* @param {number} [limit] - Maximum number to return
|
|
158
|
-
* @returns {
|
|
154
|
+
* @returns {any[]}
|
|
159
155
|
*/
|
|
160
156
|
getRecentBroadcasts(limit) {
|
|
161
157
|
const broadcasts = [...this._recentBroadcasts];
|
|
@@ -180,7 +176,7 @@ class BroadcastManager extends EventEmitter {
|
|
|
180
176
|
|
|
181
177
|
/**
|
|
182
178
|
* Gets broadcast statistics
|
|
183
|
-
* @returns {
|
|
179
|
+
* @returns {any}
|
|
184
180
|
*/
|
|
185
181
|
getStats() {
|
|
186
182
|
return {
|
|
@@ -221,7 +217,7 @@ class BroadcastManager extends EventEmitter {
|
|
|
221
217
|
/**
|
|
222
218
|
* Adds a message to recent broadcasts
|
|
223
219
|
* @private
|
|
224
|
-
* @param {
|
|
220
|
+
* @param {any} message - Message to add
|
|
225
221
|
*/
|
|
226
222
|
_addToRecent(message) {
|
|
227
223
|
this._recentBroadcasts.push(message);
|
|
@@ -233,6 +229,7 @@ class BroadcastManager extends EventEmitter {
|
|
|
233
229
|
}
|
|
234
230
|
}
|
|
235
231
|
|
|
232
|
+
/** @type {any} */
|
|
236
233
|
BroadcastManager.CONFIG = BROADCAST_CONFIG;
|
|
237
234
|
|
|
238
235
|
module.exports = BroadcastManager;
|
|
@@ -12,11 +12,7 @@
|
|
|
12
12
|
class Channel {
|
|
13
13
|
/**
|
|
14
14
|
* Creates a new Channel
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {string} options.id - Channel ID
|
|
17
|
-
* @param {string} [options.name] - Channel display name
|
|
18
|
-
* @param {string} [options.password] - Channel password (hashed)
|
|
19
|
-
* @param {number} [options.createdAt] - Creation timestamp
|
|
15
|
+
* @param {any} options - Channel options
|
|
20
16
|
*/
|
|
21
17
|
constructor(options) {
|
|
22
18
|
const { id, name, password, createdAt } = options;
|
|
@@ -25,17 +21,17 @@ class Channel {
|
|
|
25
21
|
throw new Error('Channel ID is required');
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
/** @private */
|
|
24
|
+
/** @type {string} @private */
|
|
29
25
|
this._id = id;
|
|
30
|
-
/** @private */
|
|
26
|
+
/** @type {string} @private */
|
|
31
27
|
this._name = name || id;
|
|
32
|
-
/** @private */
|
|
28
|
+
/** @type {Uint8Array | null} @private */
|
|
33
29
|
this._passwordHash = password ? this._hashPassword(password) : null;
|
|
34
|
-
/** @private */
|
|
30
|
+
/** @type {Set<string>} @private */
|
|
35
31
|
this._members = new Set();
|
|
36
|
-
/** @private */
|
|
32
|
+
/** @type {number} @private */
|
|
37
33
|
this._createdAt = createdAt || Date.now();
|
|
38
|
-
/** @private */
|
|
34
|
+
/** @type {number} @private */
|
|
39
35
|
this._joinedAt = Date.now();
|
|
40
36
|
}
|
|
41
37
|
|
|
@@ -157,7 +153,7 @@ class Channel {
|
|
|
157
153
|
|
|
158
154
|
/**
|
|
159
155
|
* Converts to JSON representation
|
|
160
|
-
* @returns {
|
|
156
|
+
* @returns {any}
|
|
161
157
|
*/
|
|
162
158
|
toJSON() {
|
|
163
159
|
return {
|
|
@@ -173,7 +169,7 @@ class Channel {
|
|
|
173
169
|
|
|
174
170
|
/**
|
|
175
171
|
* Creates a Channel from JSON
|
|
176
|
-
* @param {
|
|
172
|
+
* @param {any} json - JSON object
|
|
177
173
|
* @returns {Channel}
|
|
178
174
|
*/
|
|
179
175
|
static fromJSON(json) {
|
|
@@ -184,7 +180,7 @@ class Channel {
|
|
|
184
180
|
});
|
|
185
181
|
|
|
186
182
|
if (json.members) {
|
|
187
|
-
json.members.forEach(peerId => channel.addMember(peerId));
|
|
183
|
+
json.members.forEach((/** @type {string} */ peerId) => channel.addMember(peerId));
|
|
188
184
|
}
|
|
189
185
|
|
|
190
186
|
channel._joinedAt = json.joinedAt || Date.now();
|
|
@@ -18,7 +18,7 @@ const Channel = require('./Channel');
|
|
|
18
18
|
class ChannelManager extends EventEmitter {
|
|
19
19
|
constructor() {
|
|
20
20
|
super();
|
|
21
|
-
/** @private */
|
|
21
|
+
/** @type {Map<string, any>} @private */
|
|
22
22
|
this._channels = new Map();
|
|
23
23
|
}
|
|
24
24
|
|
|
@@ -26,7 +26,7 @@ class ChannelManager extends EventEmitter {
|
|
|
26
26
|
* Joins a channel
|
|
27
27
|
* @param {string} channelId - Channel ID
|
|
28
28
|
* @param {string} [password] - Optional password
|
|
29
|
-
* @returns {
|
|
29
|
+
* @returns {any}
|
|
30
30
|
*/
|
|
31
31
|
joinChannel(channelId, password) {
|
|
32
32
|
if (!channelId || typeof channelId !== 'string') {
|
|
@@ -57,21 +57,21 @@ class ChannelManager extends EventEmitter {
|
|
|
57
57
|
}
|
|
58
58
|
const channel = this._channels.get(channelId);
|
|
59
59
|
this._channels.delete(channelId);
|
|
60
|
-
this.emit(EVENTS.CHANNEL_LEFT, { channelId, memberCount: channel
|
|
60
|
+
this.emit(EVENTS.CHANNEL_LEFT, { channelId, memberCount: channel?.getMemberCount() });
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
64
|
* Gets all joined channels
|
|
65
|
-
* @returns {
|
|
65
|
+
* @returns {any[]}
|
|
66
66
|
*/
|
|
67
67
|
getChannels() {
|
|
68
|
-
return Array.from(this._channels.values()).map(c => c.toJSON());
|
|
68
|
+
return Array.from(this._channels.values()).map((/** @type {any} */ c) => c.toJSON());
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
72
|
* Gets a specific channel
|
|
73
73
|
* @param {string} channelId - Channel ID
|
|
74
|
-
* @returns {
|
|
74
|
+
* @returns {any}
|
|
75
75
|
*/
|
|
76
76
|
getChannel(channelId) {
|
|
77
77
|
return this._channels.get(channelId);
|
|
@@ -122,14 +122,14 @@ class ChannelManager extends EventEmitter {
|
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* Handles an incoming channel message
|
|
125
|
-
* @param {
|
|
125
|
+
* @param {any} message - Message data
|
|
126
126
|
*/
|
|
127
127
|
handleChannelMessage(message) {
|
|
128
128
|
const { channelId, senderId, content, timestamp } = message;
|
|
129
129
|
if (!this._channels.has(channelId)) { return; }
|
|
130
130
|
|
|
131
131
|
const channel = this._channels.get(channelId);
|
|
132
|
-
if (senderId && !channel.hasMember(senderId)) {
|
|
132
|
+
if (senderId && channel && !channel.hasMember(senderId)) {
|
|
133
133
|
channel.addMember(senderId);
|
|
134
134
|
this.emit(EVENTS.CHANNEL_MEMBER_JOINED, { channelId, peerId: senderId });
|
|
135
135
|
}
|
|
@@ -158,12 +158,12 @@ class ChannelManager extends EventEmitter {
|
|
|
158
158
|
|
|
159
159
|
/**
|
|
160
160
|
* Gets channel statistics
|
|
161
|
-
* @returns {
|
|
161
|
+
* @returns {any}
|
|
162
162
|
*/
|
|
163
163
|
getStats() {
|
|
164
164
|
return {
|
|
165
165
|
channelCount: this._channels.size,
|
|
166
|
-
totalMembers: Array.from(this._channels.values()).reduce((s, c) => s + c.getMemberCount(), 0)
|
|
166
|
+
totalMembers: Array.from(this._channels.values()).reduce((/** @type {number} */ s, /** @type {any} */ c) => s + c.getMemberCount(), 0)
|
|
167
167
|
};
|
|
168
168
|
}
|
|
169
169
|
}
|
|
@@ -14,38 +14,31 @@ const { generateUUID } = require('../../../utils');
|
|
|
14
14
|
class TextMessage {
|
|
15
15
|
/**
|
|
16
16
|
* Creates a new TextMessage
|
|
17
|
-
* @param {
|
|
18
|
-
* @param {string} [options.id] - Message ID
|
|
19
|
-
* @param {string} options.content - Message content
|
|
20
|
-
* @param {string} [options.senderId] - Sender peer ID
|
|
21
|
-
* @param {string} [options.recipientId] - Recipient peer ID (for private messages)
|
|
22
|
-
* @param {string} [options.channelId] - Channel ID (for channel messages)
|
|
23
|
-
* @param {number} [options.timestamp] - Message timestamp
|
|
24
|
-
* @param {boolean} [options.isRead] - Whether message has been read
|
|
17
|
+
* @param {any} options - Message options
|
|
25
18
|
*/
|
|
26
19
|
constructor(options) {
|
|
27
20
|
const { id, content, senderId, recipientId, channelId, timestamp, isRead } = options;
|
|
28
21
|
|
|
29
|
-
/** @private */
|
|
22
|
+
/** @type {string} @private */
|
|
30
23
|
this._id = id || generateUUID();
|
|
31
|
-
/** @private */
|
|
24
|
+
/** @type {string} @private */
|
|
32
25
|
this._content = content || '';
|
|
33
|
-
/** @private */
|
|
26
|
+
/** @type {string | null} @private */
|
|
34
27
|
this._senderId = senderId || null;
|
|
35
|
-
/** @private */
|
|
28
|
+
/** @type {string | null} @private */
|
|
36
29
|
this._recipientId = recipientId || null;
|
|
37
|
-
/** @private */
|
|
30
|
+
/** @type {string | null} @private */
|
|
38
31
|
this._channelId = channelId || null;
|
|
39
|
-
/** @private */
|
|
32
|
+
/** @type {number} @private */
|
|
40
33
|
this._timestamp = timestamp || Date.now();
|
|
41
|
-
/** @private */
|
|
34
|
+
/** @type {boolean} @private */
|
|
42
35
|
this._isRead = isRead || false;
|
|
43
36
|
}
|
|
44
37
|
|
|
45
38
|
/**
|
|
46
39
|
* Creates a TextMessage from a string
|
|
47
40
|
* @param {string} content - Message content
|
|
48
|
-
* @param {
|
|
41
|
+
* @param {any} [options] - Additional options
|
|
49
42
|
* @returns {TextMessage}
|
|
50
43
|
*/
|
|
51
44
|
static fromString(content, options = {}) {
|
|
@@ -253,7 +246,7 @@ class TextMessage {
|
|
|
253
246
|
|
|
254
247
|
/**
|
|
255
248
|
* Returns message metadata
|
|
256
|
-
* @returns {
|
|
249
|
+
* @returns {any}
|
|
257
250
|
*/
|
|
258
251
|
getMetadata() {
|
|
259
252
|
return {
|
|
@@ -269,7 +262,7 @@ class TextMessage {
|
|
|
269
262
|
|
|
270
263
|
/**
|
|
271
264
|
* Converts to JSON representation
|
|
272
|
-
* @returns {
|
|
265
|
+
* @returns {any}
|
|
273
266
|
*/
|
|
274
267
|
toJSON() {
|
|
275
268
|
return {
|
|
@@ -285,7 +278,7 @@ class TextMessage {
|
|
|
285
278
|
|
|
286
279
|
/**
|
|
287
280
|
* Creates a TextMessage from JSON
|
|
288
|
-
* @param {
|
|
281
|
+
* @param {any} json - JSON object
|
|
289
282
|
* @returns {TextMessage}
|
|
290
283
|
*/
|
|
291
284
|
static fromJSON(json) {
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Text header flags
|
|
10
|
-
* @constant {
|
|
10
|
+
* @constant {any}
|
|
11
11
|
*/
|
|
12
12
|
const TEXT_HEADER_FLAGS = Object.freeze({
|
|
13
13
|
HAS_SENDER: 0x01,
|
|
@@ -94,7 +94,7 @@ function createTextHeader(options) {
|
|
|
94
94
|
/**
|
|
95
95
|
* Parses a text message header
|
|
96
96
|
* @param {Uint8Array} data - Header data
|
|
97
|
-
* @returns {
|
|
97
|
+
* @returns {any}
|
|
98
98
|
*/
|
|
99
99
|
function parseTextHeader(data) {
|
|
100
100
|
if (data.length < TEXT_HEADER_SIZE) {
|
|
@@ -20,9 +20,9 @@ const Storage = require('./Storage');
|
|
|
20
20
|
class AsyncStorageAdapter extends Storage {
|
|
21
21
|
/**
|
|
22
22
|
* Creates a new AsyncStorageAdapter instance
|
|
23
|
-
* @param {
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* @param {any} [options={}] - Storage options
|
|
24
|
+
*
|
|
25
|
+
*
|
|
26
26
|
*/
|
|
27
27
|
constructor(options = {}) {
|
|
28
28
|
super({
|
|
@@ -32,7 +32,7 @@ class AsyncStorageAdapter extends Storage {
|
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* AsyncStorage instance
|
|
35
|
-
* @type {
|
|
35
|
+
* @type {any}
|
|
36
36
|
* @private
|
|
37
37
|
*/
|
|
38
38
|
this._storage = options.AsyncStorage || null;
|
|
@@ -58,6 +58,7 @@ class AsyncStorageAdapter extends Storage {
|
|
|
58
58
|
// Try to load AsyncStorage if not provided
|
|
59
59
|
if (!this._storage) {
|
|
60
60
|
try {
|
|
61
|
+
// @ts-ignore
|
|
61
62
|
const AsyncStorageModule = require('@react-native-async-storage/async-storage');
|
|
62
63
|
this._storage = AsyncStorageModule.default || AsyncStorageModule;
|
|
63
64
|
} catch (error) {
|
|
@@ -117,8 +118,8 @@ class AsyncStorageAdapter extends Storage {
|
|
|
117
118
|
* Sets a value by key
|
|
118
119
|
* @param {string} key - Key to set
|
|
119
120
|
* @param {any} value - Value to store
|
|
120
|
-
* @param {
|
|
121
|
-
*
|
|
121
|
+
* @param {any} [options={}] - Set options
|
|
122
|
+
*
|
|
122
123
|
* @returns {Promise<void>}
|
|
123
124
|
*/
|
|
124
125
|
async set(key, value, options = {}) {
|
|
@@ -126,6 +127,7 @@ class AsyncStorageAdapter extends Storage {
|
|
|
126
127
|
|
|
127
128
|
const prefixedKey = this._getKey(key);
|
|
128
129
|
|
|
130
|
+
/** @type {any} */
|
|
129
131
|
const item = {
|
|
130
132
|
value,
|
|
131
133
|
createdAt: Date.now()
|
|
@@ -170,7 +172,7 @@ class AsyncStorageAdapter extends Storage {
|
|
|
170
172
|
|
|
171
173
|
const allKeys = await this._storage.getAllKeys();
|
|
172
174
|
const prefix = `${this._options.prefix}:`;
|
|
173
|
-
const keysToRemove = allKeys.filter(key => key.startsWith(prefix));
|
|
175
|
+
const keysToRemove = allKeys.filter((/** @type {any} */ key) => key.startsWith(prefix));
|
|
174
176
|
|
|
175
177
|
if (keysToRemove.length > 0) {
|
|
176
178
|
await this._storage.multiRemove(keysToRemove);
|
|
@@ -188,8 +190,8 @@ class AsyncStorageAdapter extends Storage {
|
|
|
188
190
|
const prefix = `${this._options.prefix}:`;
|
|
189
191
|
|
|
190
192
|
return allKeys
|
|
191
|
-
.filter(key => key.startsWith(prefix))
|
|
192
|
-
.map(key => key.slice(prefix.length));
|
|
193
|
+
.filter((/** @type {any} */ key) => key.startsWith(prefix))
|
|
194
|
+
.map((/** @type {any} */ key) => key.slice(prefix.length));
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
/**
|
|
@@ -205,7 +207,7 @@ class AsyncStorageAdapter extends Storage {
|
|
|
205
207
|
const result = new Map();
|
|
206
208
|
const now = Date.now();
|
|
207
209
|
|
|
208
|
-
for (const [prefixedKey, jsonValue] of pairs) {
|
|
210
|
+
for (const [prefixedKey, jsonValue] of /** @type {any[]} */ (pairs)) {
|
|
209
211
|
if (jsonValue !== null) {
|
|
210
212
|
const key = prefixedKey.slice(this._options.prefix.length + 1);
|
|
211
213
|
try {
|
|
@@ -224,9 +226,9 @@ class AsyncStorageAdapter extends Storage {
|
|
|
224
226
|
|
|
225
227
|
/**
|
|
226
228
|
* Sets multiple key-value pairs
|
|
227
|
-
* @param {Map<string, any>|
|
|
228
|
-
* @param {
|
|
229
|
-
*
|
|
229
|
+
* @param {Map<string, any>|any} entries - Entries to set
|
|
230
|
+
* @param {any} [options={}] - Set options
|
|
231
|
+
*
|
|
230
232
|
* @returns {Promise<void>}
|
|
231
233
|
*/
|
|
232
234
|
async setMany(entries, options = {}) {
|
|
@@ -237,7 +239,8 @@ class AsyncStorageAdapter extends Storage {
|
|
|
237
239
|
: Object.entries(entries);
|
|
238
240
|
|
|
239
241
|
const now = Date.now();
|
|
240
|
-
const keyValuePairs = pairs.map(([key, value]) => {
|
|
242
|
+
const keyValuePairs = pairs.map((/** @type {any} */ [key, value]) => {
|
|
243
|
+
/** @type {any} */
|
|
241
244
|
const item = {
|
|
242
245
|
value,
|
|
243
246
|
createdAt: now
|