react-broadcast-sync 1.1.4 → 1.2.1
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/CHANGELOG.md +14 -0
- package/README.md +54 -46
- package/demo/react-broadcast-sync-demo/package.json +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/types/types.d.ts +15 -6
- package/dist/utils/debug.d.ts +4 -2
- package/dist/utils/messageUtils.d.ts +3 -6
- package/package.json +1 -1
- package/src/hooks/useBroadcastChannel.ts +75 -55
- package/src/tests/messageUtils.test.ts +6 -6
- package/src/tests/useBroadcastChannel.same-tab.test.tsx +981 -0
- package/src/tests/useBroadcastChannel.test.tsx +14 -14
- package/src/types/types.ts +18 -7
- package/src/utils/debug.ts +4 -2
- package/src/utils/messageUtils.ts +6 -7
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderHook, act } from '@testing-library/react';
|
|
2
2
|
import { useBroadcastChannel } from '../hooks/useBroadcastChannel';
|
|
3
|
+
import { getInternalMessageType } from '../utils/messageUtils';
|
|
3
4
|
|
|
4
5
|
let mockChannels: any[] = [];
|
|
5
6
|
|
|
@@ -118,7 +119,7 @@ describe('useBroadcastChannel', () => {
|
|
|
118
119
|
expect(result.current.messages.length).toBe(1);
|
|
119
120
|
|
|
120
121
|
act(() => {
|
|
121
|
-
result.current.
|
|
122
|
+
result.current.clearReceivedMessages({ ids: ['123'] });
|
|
122
123
|
});
|
|
123
124
|
|
|
124
125
|
expect(result.current.messages.length).toBe(0);
|
|
@@ -149,7 +150,7 @@ describe('useBroadcastChannel', () => {
|
|
|
149
150
|
expect(result.current.messages.length).toBe(2);
|
|
150
151
|
|
|
151
152
|
act(() => {
|
|
152
|
-
result.current.
|
|
153
|
+
result.current.clearReceivedMessages();
|
|
153
154
|
});
|
|
154
155
|
|
|
155
156
|
expect(result.current.messages.length).toBe(0);
|
|
@@ -167,7 +168,7 @@ describe('useBroadcastChannel', () => {
|
|
|
167
168
|
expect(result.current.sentMessages.length).toBe(1);
|
|
168
169
|
|
|
169
170
|
act(() => {
|
|
170
|
-
result.current.
|
|
171
|
+
result.current.clearSentMessages({ ids: [sentId] });
|
|
171
172
|
});
|
|
172
173
|
|
|
173
174
|
expect(result.current.sentMessages.length).toBe(0);
|
|
@@ -262,7 +263,7 @@ describe('useBroadcastChannel', () => {
|
|
|
262
263
|
expect(result.current.messages.length).toBe(1);
|
|
263
264
|
});
|
|
264
265
|
|
|
265
|
-
it('handles internal clear message from other source', async () => {
|
|
266
|
+
it('handles internal clear message (single id) from other source', async () => {
|
|
266
267
|
const { result } = renderHook(() => useBroadcastChannel('test-channel'));
|
|
267
268
|
await waitForChannel();
|
|
268
269
|
const channel = mockChannels[0];
|
|
@@ -279,11 +280,12 @@ describe('useBroadcastChannel', () => {
|
|
|
279
280
|
|
|
280
281
|
expect(result.current.messages.length).toBe(1);
|
|
281
282
|
|
|
283
|
+
const internalType = getInternalMessageType('CLEAR_SENT_MESSAGES', 'test-channel');
|
|
282
284
|
act(() => {
|
|
283
285
|
channel.simulateMessage({
|
|
284
|
-
id: '
|
|
285
|
-
type:
|
|
286
|
-
|
|
286
|
+
id: 'internal-1',
|
|
287
|
+
type: internalType,
|
|
288
|
+
message: { ids: ['to-clear'], types: [] },
|
|
287
289
|
source: 'another-tab',
|
|
288
290
|
timestamp: Date.now(),
|
|
289
291
|
});
|
|
@@ -292,7 +294,7 @@ describe('useBroadcastChannel', () => {
|
|
|
292
294
|
expect(result.current.messages.length).toBe(0);
|
|
293
295
|
});
|
|
294
296
|
|
|
295
|
-
it('handles internal clear all messages from other source', async () => {
|
|
297
|
+
it('handles internal clear all messages (wildcard) from other source', async () => {
|
|
296
298
|
const { result } = renderHook(() => useBroadcastChannel('test-channel'));
|
|
297
299
|
await waitForChannel();
|
|
298
300
|
const channel = mockChannels[0];
|
|
@@ -316,14 +318,12 @@ describe('useBroadcastChannel', () => {
|
|
|
316
318
|
|
|
317
319
|
expect(result.current.messages.length).toBe(2);
|
|
318
320
|
|
|
321
|
+
const internalTypeAll = getInternalMessageType('CLEAR_SENT_MESSAGES', 'test-channel');
|
|
319
322
|
act(() => {
|
|
320
323
|
channel.simulateMessage({
|
|
321
|
-
id:
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
type:
|
|
325
|
-
'__INTERNAL__:CLEAR_ALL_MESSAGES:' +
|
|
326
|
-
btoa('react-broadcast-sync:CLEAR_ALL_MESSAGES:test-channel-'),
|
|
324
|
+
id: 'internal-2',
|
|
325
|
+
type: internalTypeAll,
|
|
326
|
+
message: { ids: [], types: [] },
|
|
327
327
|
source: 'another-tab',
|
|
328
328
|
timestamp: Date.now(),
|
|
329
329
|
});
|
package/src/types/types.ts
CHANGED
|
@@ -57,6 +57,18 @@ export interface BroadcastMessage {
|
|
|
57
57
|
/** Optional expiration timestamp */
|
|
58
58
|
expirationDate?: number;
|
|
59
59
|
}
|
|
60
|
+
export interface ClearOptions {
|
|
61
|
+
ids?: string[];
|
|
62
|
+
types?: string[];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ClearReceivedMessagesOptions extends ClearOptions {
|
|
66
|
+
sources?: string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ClearSentMessagesOptions extends ClearOptions {
|
|
70
|
+
sync?: boolean;
|
|
71
|
+
}
|
|
60
72
|
|
|
61
73
|
/**
|
|
62
74
|
* Actions and state provided by the broadcast channel hook
|
|
@@ -74,15 +86,14 @@ export interface BroadcastActions {
|
|
|
74
86
|
/** Function to send a message */
|
|
75
87
|
postMessage: (messageType: string, messageContent: any, options?: SendMessageOptions) => void;
|
|
76
88
|
|
|
77
|
-
/** Function to clear
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
/** Function to clear all messages */
|
|
81
|
-
clearAllMessages: () => void;
|
|
89
|
+
/** Function to clear received messages */
|
|
90
|
+
clearReceivedMessages: (options?: ClearReceivedMessagesOptions) => void;
|
|
82
91
|
|
|
83
|
-
/** Function to clear
|
|
84
|
-
|
|
92
|
+
/** Function to clear sent messages */
|
|
93
|
+
clearSentMessages: (options?: ClearSentMessagesOptions) => void;
|
|
85
94
|
|
|
86
95
|
/** Current error state */
|
|
87
96
|
error: string | null;
|
|
88
97
|
}
|
|
98
|
+
|
|
99
|
+
export type ClearMessage = 'CLEAR_SENT_MESSAGES';
|
package/src/utils/debug.ts
CHANGED
|
@@ -29,8 +29,8 @@ const log = (level: LogLevel, message: string, data?: any) => {
|
|
|
29
29
|
|
|
30
30
|
export const debug = {
|
|
31
31
|
channel: {
|
|
32
|
-
created: (
|
|
33
|
-
closed: (
|
|
32
|
+
created: (name: string) => log('info', 'Channel created:', name),
|
|
33
|
+
closed: (name: string) => log('info', 'Channel closed:', name),
|
|
34
34
|
},
|
|
35
35
|
message: {
|
|
36
36
|
sent: (message: any) => log('info', 'Message sent:', message),
|
|
@@ -38,6 +38,8 @@ export const debug = {
|
|
|
38
38
|
cleared: (messageId: string) => log('info', 'Message cleared:', messageId),
|
|
39
39
|
expired: (messageId: string) => log('info', 'Message expired:', messageId),
|
|
40
40
|
duplicate: (messageId: string) => log('warn', 'Duplicate message ignored:', messageId),
|
|
41
|
+
allSentCleared: () => log('info', 'All sent messages cleared'),
|
|
42
|
+
allReceivedCleared: () => log('info', 'All received messages cleared'),
|
|
41
43
|
},
|
|
42
44
|
cleanup: {
|
|
43
45
|
started: () => log('info', 'Cleanup started'),
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ClearMessage } from '../types/types';
|
|
2
|
+
|
|
1
3
|
const INTERNAL_PREFIX = '__INTERNAL__';
|
|
2
4
|
const SECRET = 'react-broadcast-sync';
|
|
3
5
|
|
|
@@ -44,7 +46,7 @@ export const createMessage = (
|
|
|
44
46
|
};
|
|
45
47
|
|
|
46
48
|
export const getInternalMessageType = (
|
|
47
|
-
baseType:
|
|
49
|
+
baseType: ClearMessage,
|
|
48
50
|
channelName: string,
|
|
49
51
|
namespace = ''
|
|
50
52
|
): string => {
|
|
@@ -58,16 +60,13 @@ export const isInternalType = (type: string): boolean => {
|
|
|
58
60
|
return type.startsWith(`${INTERNAL_PREFIX}:`);
|
|
59
61
|
};
|
|
60
62
|
|
|
61
|
-
export const isValidInternalClearMessage = (
|
|
62
|
-
message: any
|
|
63
|
-
): message is { id: string; type: string; source: string } => {
|
|
63
|
+
export const isValidInternalClearMessage = (message: any): boolean => {
|
|
64
64
|
return (
|
|
65
65
|
message &&
|
|
66
66
|
typeof message === 'object' &&
|
|
67
|
-
typeof message.id === 'string' &&
|
|
68
|
-
typeof message.source === 'string' &&
|
|
69
67
|
typeof message.type === 'string' &&
|
|
70
|
-
isInternalType(message.type)
|
|
68
|
+
isInternalType(message.type) &&
|
|
69
|
+
typeof message.source === 'string'
|
|
71
70
|
);
|
|
72
71
|
};
|
|
73
72
|
|