@folklore/socket 0.4.30 → 0.4.33

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/dist/cjs.js DELETED
@@ -1,961 +0,0 @@
1
- 'use strict';
2
-
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
5
- var createDebug = require('debug');
6
- var invariant = require('invariant');
7
- var isFunction = require('lodash/isFunction');
8
- var EventEmitter = require('wolfy87-eventemitter');
9
- var isString = require('lodash/isString');
10
- var isArray = require('lodash/isArray');
11
- var React = require('react');
12
- var PropTypes = require('prop-types');
13
- var jsxRuntime = require('react/jsx-runtime');
14
-
15
- const debug$3 = createDebug('folklore:socket:pubnub');
16
- class PubNubSocket extends EventEmitter {
17
- constructor(opts) {
18
- super();
19
- this.options = {
20
- uuid: null,
21
- publishKey: null,
22
- subscribeKey: null,
23
- secretKey: null,
24
- userId: null,
25
- withPresence: false,
26
- ...opts
27
- };
28
- this.onReady = this.onReady.bind(this);
29
- this.onStatus = this.onStatus.bind(this);
30
- this.onMessage = this.onMessage.bind(this);
31
- this.destroyed = false;
32
- this.ready = false;
33
- this.shouldStart = false;
34
- this.started = false;
35
- this.starting = false;
36
- this.PubNub = null;
37
- this.pubnub = null;
38
- this.pubnubListener = null;
39
- this.channels = [];
40
- this.init();
41
- }
42
- onReady() {
43
- if (this.destroyed) {
44
- return;
45
- }
46
- this.ready = true;
47
- this.emit('ready');
48
- }
49
- onStatus(statusEvent) {
50
- if (statusEvent.category === 'PNConnectedCategory' && !this.started) {
51
- this.started = true;
52
- this.starting = false;
53
- this.emit('started');
54
- }
55
- }
56
- onMessage({
57
- message
58
- }) {
59
- this.emit('message', message);
60
- if (typeof message.event !== 'undefined') {
61
- this.emit(message.event, message.data || message);
62
- }
63
- }
64
- updateChannels(channels) {
65
- debug$3(`Updating channels: ${channels.join(', ')}`);
66
- const {
67
- shouldStart,
68
- started,
69
- starting
70
- } = this;
71
- if (started || starting) {
72
- this.stop();
73
- }
74
- this.channels = channels;
75
- if (started || starting || shouldStart) {
76
- this.shouldStart = false;
77
- this.start();
78
- }
79
- }
80
- init() {
81
- if (this.pubnub !== null) {
82
- return;
83
- }
84
- debug$3('Init');
85
- this.destroyed = false;
86
- const loadPubnub = this.PubNub !== null ? Promise.resolve() : this.loadPubNub();
87
- loadPubnub.then(() => this.createPubNub()).then(() => this.onReady());
88
- }
89
- loadPubNub() {
90
- debug$3('Load PubNub');
91
- return import('pubnub').then(({
92
- default: PubNub
93
- }) => {
94
- this.PubNub = PubNub;
95
- });
96
- }
97
- createPubNub() {
98
- if (this.destroyed) {
99
- return;
100
- }
101
- const {
102
- PubNub
103
- } = this;
104
- const pubnubOptions = {
105
- publishKey: this.options.publishKey,
106
- subscribeKey: this.options.subscribeKey,
107
- userId: `web-user-${Math.floor(Math.random() * 1000)}`
108
- };
109
- if (this.options.uuid !== null) {
110
- pubnubOptions.uuid = this.options.uuid;
111
- }
112
- if (this.options.userId !== null) {
113
- pubnubOptions.userId = this.options.userId;
114
- }
115
- if (this.options.secretKey !== null) {
116
- pubnubOptions.secretKey = this.options.secretKey;
117
- }
118
- this.pubnub = new PubNub(pubnubOptions);
119
- this.pubnubListener = {
120
- status: this.onStatus,
121
- message: this.onMessage
122
- };
123
- this.pubnub.addListener(this.pubnubListener);
124
- }
125
- destroy() {
126
- this.destroyed = true;
127
- this.stop();
128
- if (this.pubnubListener) {
129
- this.pubnub.removeListener(this.pubnubListener);
130
- this.pubnubListener = null;
131
- }
132
- this.pubnub = null;
133
- this.ready = false;
134
- debug$3('Destroyed.');
135
- }
136
- start() {
137
- if (this.started) {
138
- debug$3('Skipping start: Already started.');
139
- return;
140
- }
141
- if (this.starting) {
142
- debug$3('Skipping start: Already starting.');
143
- return;
144
- }
145
- if (this.channels.length === 0) {
146
- debug$3('Skipping start: No channels.');
147
- this.shouldStart = true;
148
- return;
149
- }
150
- const {
151
- subscriptionOptions,
152
- withPresence
153
- } = this.options;
154
- this.shouldStart = false;
155
- this.starting = true;
156
- this.pubnub.subscribe({
157
- channels: this.channels,
158
- subscriptionOptions,
159
- withPresence
160
- });
161
- this.emit('start');
162
- }
163
- stop() {
164
- if (!this.started && !this.starting) {
165
- return;
166
- }
167
- debug$3('Stopping...');
168
- this.shouldStart = false;
169
- this.started = false;
170
- this.starting = false;
171
- this.pubnub.unsubscribe({
172
- channels: this.channels
173
- });
174
- this.emit('stop');
175
- }
176
- send(data) {
177
- debug$3('Sending', data);
178
- return new Promise((resolve, reject) => {
179
- this.pubnub.publish(data, (status, response) => {
180
- if (status.error) {
181
- reject(new Error(`Error operation:${status.operation} status:${status.statusCode}`));
182
- } else {
183
- resolve({
184
- status,
185
- response,
186
- data
187
- });
188
- }
189
- });
190
- });
191
- }
192
- }
193
-
194
- const debug$2 = createDebug('folklore:socket:socketio');
195
- class SocketIOSocket extends EventEmitter {
196
- constructor(opts) {
197
- super();
198
- this.options = {
199
- uuid: null,
200
- host: 'http://127.0.0.1',
201
- path: null,
202
- query: null,
203
- ...opts
204
- };
205
- this.onReady = this.onReady.bind(this);
206
- this.onConnect = this.onConnect.bind(this);
207
- this.onMessage = this.onMessage.bind(this);
208
- this.ready = false;
209
- this.shouldStart = false;
210
- this.started = false;
211
- this.starting = false;
212
- this.Manager = null;
213
- this.io = null;
214
- this.sockets = {};
215
- this.channels = [];
216
- this.init();
217
- }
218
- onReady() {
219
- this.ready = true;
220
- this.emit('ready');
221
- }
222
- onConnect(channel) {
223
- debug$2('Socket connected on %s', channel);
224
- if (!this.started) {
225
- this.started = true;
226
- this.starting = false;
227
- this.emit('started');
228
- }
229
- }
230
- onMessage(message, channel) {
231
- debug$2('Message received on %s %o', channel, message);
232
- this.emit('message', message, channel);
233
- }
234
- init() {
235
- import('socket.io-client').then(({
236
- default: IO
237
- }) => {
238
- this.Manager = IO.Manager;
239
- }).then(() => this.createManager()).then(() => this.onReady()).then(() => {
240
- if (this.shouldStart) {
241
- this.start();
242
- }
243
- });
244
- }
245
- createManager() {
246
- const {
247
- Manager
248
- } = this;
249
- const {
250
- host,
251
- ...opts
252
- } = this.options;
253
- this.io = new Manager(host, {
254
- autoConnect: false,
255
- ...opts
256
- });
257
- }
258
- updateChannels(channels) {
259
- debug$2(`Updating channels: ${channels.join(', ')}`);
260
- const {
261
- shouldStart,
262
- started,
263
- starting
264
- } = this;
265
- if (started || starting) {
266
- this.stop();
267
- }
268
- this.channels = channels;
269
- if (started || starting || shouldStart) {
270
- this.start();
271
- }
272
- }
273
- start() {
274
- if (this.started) {
275
- debug$2('Skipping start: Already started.');
276
- return;
277
- }
278
- if (this.starting) {
279
- debug$2('Skipping start: Already starting.');
280
- return;
281
- }
282
- if (this.io === null) {
283
- debug$2('Socket.io not ready.');
284
- this.shouldStart = true;
285
- return;
286
- }
287
- if (this.channels.length === 0) {
288
- debug$2('Skipping start: No channels.');
289
- this.shouldStart = true;
290
- return;
291
- }
292
- this.shouldStart = false;
293
- this.starting = true;
294
- this.sockets = this.channels.reduce((map, channel) => ({
295
- ...map,
296
- [channel]: this.createSocket(channel)
297
- }), {});
298
- this.emit('start');
299
- }
300
- stop() {
301
- if (!this.started && !this.starting) {
302
- return;
303
- }
304
- debug$2('Stopping...');
305
- this.shouldStart = false;
306
- this.started = false;
307
- this.starting = false;
308
- Object.values(this.sockets).forEach(socket => this.stopSocket(socket));
309
- this.emit('stop');
310
- }
311
- createSocket(channel) {
312
- const socket = this.io.socket(`/${channel.replace(/^\//, '')}`);
313
- socket.on('message', message => this.onMessage(message, channel));
314
- socket.on('connect', () => this.onConnect(channel));
315
- socket.open();
316
- return socket;
317
- }
318
-
319
- // eslint-disable-next-line class-methods-use-this
320
- stopSocket(socket) {
321
- socket.off('connect');
322
- socket.off('message');
323
- socket.close();
324
- return socket;
325
- }
326
- destroy() {
327
- this.stop();
328
- this.sockets = {};
329
- if (this.io !== null) {
330
- this.io.close();
331
- this.io = null;
332
- }
333
- }
334
- send(data) {
335
- const {
336
- channel,
337
- message
338
- } = data;
339
- const channels = !isArray(channel) ? [channel] : channel;
340
- channels.forEach(ch => {
341
- this.sockets[ch].send(message);
342
- });
343
- return Promise.resolve();
344
- }
345
- }
346
-
347
- const debug$1 = createDebug('folklore:socket:pusher');
348
- class PusherSocket extends EventEmitter {
349
- constructor(opts) {
350
- super();
351
- this.options = {
352
- uuid: null,
353
- publishKey: null,
354
- subscribeKey: null,
355
- secretKey: null,
356
- ...opts
357
- };
358
- this.onReady = this.onReady.bind(this);
359
- this.onConnected = this.onConnected.bind(this);
360
- this.onMessage = this.onMessage.bind(this);
361
- this.destroyed = false;
362
- this.ready = false;
363
- this.shouldStart = false;
364
- this.started = false;
365
- this.starting = false;
366
- this.Pusher = null;
367
- this.pusher = null;
368
- this.channels = [];
369
- this.clients = {};
370
- this.init();
371
- }
372
- onReady() {
373
- if (this.destroyed) {
374
- return;
375
- }
376
- this.ready = true;
377
- this.emit('ready');
378
- }
379
- onConnected() {
380
- this.started = true;
381
- this.starting = false;
382
- this.emit('started');
383
- }
384
- onMessage(message) {
385
- this.emit('message', message);
386
- if (typeof message.event !== 'undefined') {
387
- this.emit(message.event, message.data || message);
388
- }
389
- }
390
- updateChannels(channels) {
391
- debug$1(`Updating channels: ${channels.join(', ')}`);
392
- const {
393
- shouldStart,
394
- started,
395
- starting
396
- } = this;
397
- if (started || starting) {
398
- this.stop();
399
- }
400
- this.channels = channels;
401
- if (started || starting || shouldStart) {
402
- this.shouldStart = false;
403
- this.start();
404
- }
405
- }
406
- init() {
407
- if (this.pusher !== null) {
408
- return;
409
- }
410
- debug$1('Init');
411
- this.destroyed = false;
412
- const loadPusher = this.Pusher !== null ? Promise.resolve() : this.loadPusher();
413
- loadPusher.then(() => this.createPusher()).then(() => this.onReady());
414
- }
415
- loadPusher() {
416
- debug$1('Load Pusher');
417
- return import('pusher-js').then(({
418
- default: Pusher
419
- }) => {
420
- this.Pusher = Pusher;
421
- });
422
- }
423
- createPusher() {
424
- if (this.destroyed) {
425
- return;
426
- }
427
- debug$1('Create Pusher appKey: %s', this.options.appKey);
428
- const {
429
- Pusher
430
- } = this;
431
- const {
432
- appKey,
433
- ...options
434
- } = this.options;
435
- this.pusher = new Pusher(appKey, options);
436
- }
437
- destroy() {
438
- this.destroyed = true;
439
- this.stop();
440
- this.pusher = null;
441
- this.clients = {};
442
- this.ready = false;
443
- debug$1('Destroyed.');
444
- }
445
- start() {
446
- if (this.started) {
447
- debug$1('Skipping start: Already started.');
448
- return;
449
- }
450
- if (this.starting) {
451
- debug$1('Skipping start: Already starting.');
452
- return;
453
- }
454
- if (this.pusher === null) {
455
- debug$1('Socket.io not ready.');
456
- this.shouldStart = true;
457
- return;
458
- }
459
- if (this.channels.length === 0) {
460
- debug$1('Skipping start: No channels.');
461
- this.shouldStart = true;
462
- return;
463
- }
464
- this.shouldStart = false;
465
- this.starting = true;
466
- this.pusher.connection.bind('connected', this.onConnected);
467
- this.clients = this.channels.reduce((map, channel) => ({
468
- ...map,
469
- [channel]: this.createClient(channel)
470
- }), {});
471
- this.emit('start');
472
- }
473
- stop() {
474
- if (!this.started && !this.starting) {
475
- return;
476
- }
477
- debug$1('Stopping...');
478
- this.shouldStart = false;
479
- this.started = false;
480
- this.starting = false;
481
- this.pusher.connection.unbind('connected');
482
- Object.keys(this.clients).forEach(channelName => this.stopClient(channelName, this.clients[channelName]));
483
- this.clients = {};
484
- this.emit('stop');
485
- }
486
- createClient(channelName) {
487
- const channel = this.pusher.subscribe(channelName);
488
- channel.bind_global((event, data) => this.onMessage({
489
- event,
490
- data
491
- }, channel));
492
- return channel;
493
- }
494
-
495
- // eslint-disable-next-line class-methods-use-this
496
- stopClient(channelName, channel) {
497
- channel.unbind_global();
498
- this.pusher.unsubscribe(channelName);
499
- return channel;
500
- }
501
- send(data) {
502
- debug$1('Sending', data);
503
- return new Promise(resolve => {
504
- const {
505
- channel,
506
- event = null,
507
- data: eventData
508
- } = data;
509
- this.pusher.trigger(channel, event || 'message', eventData);
510
- resolve();
511
- });
512
- }
513
- }
514
-
515
- var SocketAdapters = {
516
- PubNub: PubNubSocket,
517
- SocketIO: SocketIOSocket,
518
- Pusher: PusherSocket
519
- };
520
-
521
- const normalize = str => str.replace(/[^a-z0-9]+/gi, '').toLowerCase();
522
- const debug = createDebug('folklore:socket');
523
- class Socket extends EventEmitter {
524
- static getAdapters() {
525
- return Socket.adapters;
526
- }
527
- static getAdapter(adapter) {
528
- // prettier-ignore
529
- const adapterKey = Object.keys(Socket.adapters).find(key => normalize(key) === normalize(adapter)) || null;
530
- if (adapterKey === null) {
531
- throw new Error(`Adapter ${adapter} not found`);
532
- }
533
- return Socket.adapters[adapterKey];
534
- }
535
- static addAdapter(name, adapter) {
536
- Socket.adapters = {
537
- ...Socket.adapters,
538
- [name]: adapter
539
- };
540
- return Socket;
541
- }
542
- static setAdapters(adapters) {
543
- Socket.adapters = adapters;
544
- return Socket;
545
- }
546
- constructor(opts) {
547
- super();
548
- this.options = {
549
- adapter: 'pubnub',
550
- namespace: null,
551
- uuid: null,
552
- publishKey: null,
553
- subscribeKey: null,
554
- secretKey: null,
555
- channels: [],
556
- ...opts
557
- };
558
- this.onAdapterReady = this.onAdapterReady.bind(this);
559
- this.onAdapterStart = this.onAdapterStart.bind(this);
560
- this.onAdapterStarted = this.onAdapterStarted.bind(this);
561
- this.onAdapterMessage = this.onAdapterMessage.bind(this);
562
- this.onAdapterStop = this.onAdapterStop.bind(this);
563
- this.shouldStart = false;
564
- this.started = false;
565
- this.starting = false;
566
- this.ready = false;
567
- this.adapter = null;
568
- this.channels = [];
569
- this.init();
570
- if (this.options.channels.length) {
571
- this.setChannels(this.options.channels);
572
- }
573
- }
574
- onAdapterReady() {
575
- debug('Adapter ready');
576
- this.ready = true;
577
- this.emit('ready');
578
- if (this.shouldStart) {
579
- this.shouldStart = false;
580
- this.start();
581
- }
582
- }
583
- onAdapterStart() {
584
- debug('Adapter starting...');
585
- this.starting = true;
586
- this.started = false;
587
- this.emit('start');
588
- }
589
- onAdapterStarted() {
590
- debug('Adapter started');
591
- this.starting = false;
592
- this.started = true;
593
- this.emit('started');
594
- }
595
- onAdapterStop() {
596
- debug('Adapter stopped');
597
- this.starting = false;
598
- this.started = false;
599
- this.emit('stop');
600
- }
601
- onAdapterMessage(message) {
602
- debug('Adapter message', message);
603
- this.emit('message', message);
604
- }
605
- getChannelWithoutNamespace(name) {
606
- if (this.options.namespace === null) {
607
- return name;
608
- }
609
- const regExp = new RegExp(`^${this.options.namespace}:`);
610
- return name.replace(regExp, '');
611
- }
612
- getChannelWithNamespace(name) {
613
- const parts = [];
614
- if (this.options.namespace !== null) {
615
- parts.push(this.options.namespace);
616
- }
617
- parts.push(name);
618
- return parts.join(':');
619
- }
620
- setChannels(channels) {
621
- const namespacedChannels = channels.map(channel => this.getChannelWithNamespace(channel)).sort();
622
- if (this.channels.join(',') === namespacedChannels.join(',')) {
623
- return;
624
- }
625
- debug(`Set channels: ${namespacedChannels.join(', ')}`);
626
- this.updateChannels(namespacedChannels);
627
- }
628
- addChannel(channel) {
629
- const namespacedChannel = this.getChannelWithNamespace(channel);
630
- if (this.channels.indexOf(namespacedChannel) !== -1) {
631
- return;
632
- }
633
- debug(`Adding channel: ${channel}`);
634
- this.updateChannels([...this.channels, namespacedChannel]);
635
- }
636
- addChannels(channels) {
637
- const namespacedChannels = channels.map(channel => this.getChannelWithNamespace(channel)).sort();
638
- debug(`Adding channels: ${channels.join(',')}`);
639
- this.updateChannels([...this.channels, ...namespacedChannels.filter(it => this.channels.indexOf(it) === -1)]);
640
- }
641
- removeChannel(channel) {
642
- const namespacedChannel = this.getChannelWithNamespace(channel);
643
- if (this.channels.indexOf(namespacedChannel) === -1) {
644
- return;
645
- }
646
- debug(`Removing channel: ${channel}`);
647
- this.updateChannels(this.channels.filter(ch => ch !== namespacedChannel));
648
- }
649
- removeChannels(channels) {
650
- const namespacedChannels = channels.map(channel => this.getChannelWithNamespace(channel)).sort();
651
- debug(`Removing channels: ${channels.join(',')}`);
652
- this.updateChannels(this.channels.filter(it => namespacedChannels.indexOf(it) === -1));
653
- }
654
- updateChannels(channels) {
655
- const sortedChannels = channels.sort();
656
- debug(`Updating channels: ${sortedChannels.join(', ')}`);
657
- this.channels = [...sortedChannels];
658
- if (this.adapter !== null) {
659
- this.adapter.updateChannels(sortedChannels);
660
- }
661
- }
662
- hasChannel(channel) {
663
- const namespacedChannel = this.getChannelWithNamespace(channel);
664
- return this.channels.reduce((found, it) => found || it === namespacedChannel, false);
665
- }
666
- getChannels() {
667
- return this.channels.map(channel => this.getChannelWithoutNamespace(channel));
668
- }
669
- init() {
670
- if (this.adapter !== null) {
671
- debug('Already initialized');
672
- return;
673
- }
674
- debug('Init');
675
- const {
676
- adapter: adapterKey,
677
- channels,
678
- ...adapterOptions
679
- } = this.options;
680
- const SocketAdapter = isString(adapterKey) ? Socket.getAdapter(adapterKey) : adapterKey;
681
- this.adapter = new SocketAdapter(adapterOptions);
682
- const methods = ['start', 'stop', 'destroy', 'updateChannels', 'send'];
683
- methods.forEach(method => {
684
- invariant(isFunction(this.adapter[method] || null), `Socket adapter should implement method ${method}`);
685
- });
686
- this.adapter.on('ready', this.onAdapterReady);
687
- this.adapter.on('start', this.onAdapterStart);
688
- this.adapter.on('started', this.onAdapterStarted);
689
- this.adapter.on('message', this.onAdapterMessage);
690
- this.adapter.on('stop', this.onAdapterStop);
691
- this.adapter.updateChannels(this.channels);
692
- }
693
- destroy() {
694
- if (this.adapter !== null) {
695
- this.adapter.removeAllListeners();
696
- this.adapter.destroy();
697
- this.adapter = null;
698
- }
699
- this.started = false;
700
- this.starting = false;
701
- this.ready = false;
702
- debug('Destroyed.');
703
- }
704
- restart() {
705
- this.stop();
706
- this.start();
707
- }
708
- start() {
709
- if (this.started) {
710
- debug('Skipping start: Already started.');
711
- return;
712
- }
713
- if (this.starting) {
714
- debug('Skipping start: Already starting.');
715
- return;
716
- }
717
- if (!this.ready) {
718
- debug('Skipping start: No ready.');
719
- this.shouldStart = true;
720
- return;
721
- }
722
- this.shouldStart = false;
723
- debug('Starting on channels:');
724
- this.channels.forEach(channel => {
725
- debug(`- ${this.getChannelWithoutNamespace(channel)}`);
726
- });
727
- this.adapter.start();
728
- }
729
- stop() {
730
- this.shouldStart = false;
731
- if (!this.started && !this.starting) {
732
- return;
733
- }
734
- debug('Stopping...');
735
- if (this.adapter !== null) {
736
- this.adapter.stop();
737
- }
738
- }
739
- send(data, channel) {
740
- if (!this.started) {
741
- debug('Abort sending data: Not started');
742
- return Promise.reject();
743
- }
744
- const publishData = typeof data.channel !== 'undefined' && typeof data.message !== 'undefined' ? data : {
745
- channel: typeof channel !== 'undefined' ? this.getChannelWithNamespace(channel) : this.channels,
746
- message: data
747
- };
748
- debug('Sending', publishData);
749
- return this.adapter.send(publishData);
750
- }
751
- isStarted() {
752
- return this.started;
753
- }
754
- }
755
- Socket.adapters = {
756
- ...SocketAdapters
757
- };
758
-
759
- const SocketContext = /*#__PURE__*/React.createContext({
760
- socket: null,
761
- subscribe: () => {},
762
- unsubscribe: () => {}
763
- });
764
-
765
- const propTypes = {
766
- socket: PropTypes.instanceOf(Socket),
767
- adapter: PropTypes.string,
768
- host: PropTypes.string,
769
- namespace: PropTypes.string,
770
- uuid: PropTypes.string,
771
- publishKey: PropTypes.string,
772
- subscribeKey: PropTypes.string,
773
- secretKey: PropTypes.string,
774
- channels: PropTypes.arrayOf(PropTypes.string),
775
- autoStart: PropTypes.bool,
776
- children: PropTypes.node
777
- };
778
- const defaultProps = {
779
- socket: null,
780
- adapter: 'pubnub',
781
- host: null,
782
- namespace: null,
783
- uuid: null,
784
- publishKey: null,
785
- subscribeKey: null,
786
- secretKey: null,
787
- channels: [],
788
- autoStart: false,
789
- children: null
790
- };
791
- function SocketContainer({
792
- children,
793
- socket,
794
- autoStart,
795
- adapter,
796
- host,
797
- namespace,
798
- uuid,
799
- publishKey,
800
- subscribeKey,
801
- secretKey,
802
- channels: initialChannels,
803
- ...props
804
- }) {
805
- const finalSocket = React.useMemo(() => socket || new Socket({
806
- ...props,
807
- adapter,
808
- host,
809
- namespace,
810
- uuid,
811
- publishKey,
812
- subscribeKey,
813
- secretKey
814
- }), [socket, host, adapter, namespace, uuid, publishKey, subscribeKey, secretKey]);
815
- const [channels, setChannels] = React.useState([]);
816
- const channelsCountRef = React.useRef({});
817
- const updateChannels = React.useCallback(newChannels => {
818
- finalSocket.setChannels(newChannels);
819
- setChannels(newChannels);
820
- }, [finalSocket, setChannels]);
821
- const addToChannelsCount = React.useCallback(newChannels => {
822
- channelsCountRef.current = newChannels.reduce((map, channel) => ({
823
- ...map,
824
- [channel]: (map[channel] || 0) + 1
825
- }), channelsCountRef.current);
826
- updateChannels(Object.keys(channelsCountRef.current));
827
- }, [updateChannels]);
828
- const removeToChannelsCount = React.useCallback(newChannels => {
829
- channelsCountRef.current = newChannels.reduce((map, channel) => {
830
- const {
831
- [channel]: currentCount = 0,
832
- ...otherCount
833
- } = map;
834
- const newCount = (currentCount || 0) - 1;
835
- return newCount > 0 ? {
836
- ...otherCount,
837
- [channel]: newCount
838
- } : otherCount;
839
- }, channelsCountRef.current);
840
- updateChannels(Object.keys(channelsCountRef.current));
841
- }, [updateChannels]);
842
- const subscribe = React.useCallback(channelsToAdd => addToChannelsCount(channelsToAdd), [addToChannelsCount]);
843
- const unsubscribe = React.useCallback(channelsToRemove => removeToChannelsCount(channelsToRemove), [removeToChannelsCount]);
844
- React.useEffect(() => {
845
- subscribe(initialChannels);
846
- return () => {
847
- unsubscribe(initialChannels);
848
- };
849
- }, [initialChannels, subscribe, unsubscribe]);
850
- React.useEffect(() => {
851
- finalSocket.init();
852
- if (autoStart) {
853
- finalSocket.start();
854
- }
855
- return () => {
856
- finalSocket.destroy();
857
- };
858
- }, [autoStart, finalSocket]);
859
- const value = React.useMemo(() => ({
860
- socket: finalSocket,
861
- subscribe,
862
- unsubscribe,
863
- channels
864
- }), [finalSocket, subscribe]);
865
- return /*#__PURE__*/jsxRuntime.jsx(SocketContext.Provider, {
866
- value: value,
867
- children: children
868
- });
869
- }
870
- SocketContainer.propTypes = propTypes;
871
- SocketContainer.defaultProps = defaultProps;
872
-
873
- const getDisplayName = WrappedComponent => WrappedComponent.displayName || WrappedComponent.name || 'Component';
874
- const withSocket = WrappedComponent => {
875
- const WithSocketComponent = props => /*#__PURE__*/jsxRuntime.jsx(SocketContext.Consumer, {
876
- children: ({
877
- socket,
878
- subscribe,
879
- unsubscribe
880
- }) => /*#__PURE__*/jsxRuntime.jsx(WrappedComponent, {
881
- socket: socket,
882
- socketSubscribe: subscribe,
883
- socketUnsubscribe: unsubscribe,
884
- ...props
885
- })
886
- });
887
- WithSocketComponent.displayName = `WithSocket(${getDisplayName(WrappedComponent)})`;
888
- return WithSocketComponent;
889
- };
890
-
891
- const useSocket = (channelNames = null, {
892
- socket: customSocket = null,
893
- onMessage: customOnMessage = null,
894
- keepAlive = true
895
- } = {}) => {
896
- const {
897
- socket: contextSocket,
898
- subscribe,
899
- unsubscribe
900
- } = React.useContext(SocketContext);
901
- const socket = customSocket || contextSocket || null;
902
- const [started, setStarted] = React.useState(socket !== null ? socket.isStarted() : false);
903
- const channels = isString(channelNames) ? [channelNames] : channelNames;
904
- const channelsKey = (channels || []).sort().join(',');
905
- React.useEffect(() => {
906
- if (socket === null) {
907
- if (process.env.NODE_ENV !== 'production') {
908
- console.warn('Socket context is empty.');
909
- }
910
- return () => {};
911
- }
912
- const wasStarted = socket.isStarted();
913
- const onStarted = () => setStarted(true);
914
- const onStop = () => setStarted(false);
915
- socket.on('stop', onStop);
916
- socket.on('started', onStarted);
917
- if (channels !== null) {
918
- subscribe(channels);
919
- }
920
- if (!wasStarted) {
921
- socket.start();
922
- }
923
- return () => {
924
- socket.off('stop', onStop);
925
- socket.off('started', onStarted);
926
- if (channels !== null) {
927
- unsubscribe(channels);
928
- }
929
- if (socket.isStarted() && !keepAlive) {
930
- socket.stop();
931
- }
932
- };
933
- }, [channelsKey, customSocket, keepAlive]);
934
- React.useEffect(() => {
935
- if (socket === null) {
936
- return () => {};
937
- }
938
- const onMessage = (...args) => {
939
- if (customOnMessage !== null) {
940
- customOnMessage(...args);
941
- }
942
- };
943
- socket.on('message', onMessage);
944
- return () => {
945
- socket.off('message', onMessage);
946
- };
947
- }, [customOnMessage]);
948
- return {
949
- socket,
950
- started,
951
- subscribe,
952
- unsubscribe
953
- };
954
- };
955
-
956
- exports.Socket = Socket;
957
- exports.SocketContainer = SocketContainer;
958
- exports.SocketContext = SocketContext;
959
- exports.default = Socket;
960
- exports.useSocket = useSocket;
961
- exports.withSocket = withSocket;