react-broadcast-sync 1.4.0 → 1.5.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 CHANGED
@@ -1,3 +1,17 @@
1
+ ## [1.5.1](https://github.com/IdanShalem/react-broadcast-sync/compare/v1.5.0...v1.5.1) (2025-07-03)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * added readme for batching ([568a52c](https://github.com/IdanShalem/react-broadcast-sync/commit/568a52c4d23443a1e4c2a0c2ab10a6c618c68529))
7
+
8
+ # [1.5.0](https://github.com/IdanShalem/react-broadcast-sync/compare/v1.4.0...v1.5.0) (2025-07-03)
9
+
10
+
11
+ ### Features
12
+
13
+ * batch messages with delay ([6dde9fa](https://github.com/IdanShalem/react-broadcast-sync/commit/6dde9fa441e2f5fc4745c00fdbabdf48f697d58b))
14
+
1
15
  # [1.4.0](https://github.com/IdanShalem/react-broadcast-sync/compare/v1.3.0...v1.4.0) (2025-06-29)
2
16
 
3
17
 
package/README.md CHANGED
@@ -228,20 +228,24 @@ interface BroadcastOptions {
228
228
  namespace?: string; // Channel namespace for isolation
229
229
  deduplicationTTL?: number; // Time in ms to keep message IDs for deduplication (default: 5 minutes)
230
230
  cleanupDebounceMs?: number; // Debounce time in ms for cleanup operations (default: 0)
231
+ batchingDelayMs?: number; // Delay in ms to batch outgoing messages (default: 20). If > 0, messages are batched and sent together.
232
+ excludedBatchMessageTypes?: string[]; // Message types to always send immediately, never batched (default: []).
231
233
  }
232
234
  ```
233
235
 
234
236
  #### Default Values
235
237
 
236
- | Option | Default Value | Description |
237
- | ------------------- | ------------- | ----------------------------------- |
238
- | `sourceName` | `undefined` | Auto-generated if not provided |
239
- | `cleaningInterval` | `1000` | 1 second between cleanup runs |
240
- | `keepLatestMessage` | `false` | Keep all messages by default |
241
- | `registeredTypes` | `[]` | Accept all message types by default |
242
- | `namespace` | `''` | No namespace by default |
243
- | `deduplicationTTL` | `300000` | 5 minutes (5 _ 60 _ 1000 ms) |
244
- | `cleanupDebounceMs` | `0` | No debounce by default |
238
+ | Option | Default Value | Description |
239
+ | --------------------------- | ------------- | ----------------------------------- |
240
+ | `sourceName` | `undefined` | Auto-generated if not provided |
241
+ | `cleaningInterval` | `1000` | 1 second between cleanup runs |
242
+ | `keepLatestMessage` | `false` | Keep all messages by default |
243
+ | `registeredTypes` | `[]` | Accept all message types by default |
244
+ | `namespace` | `''` | No namespace by default |
245
+ | `deduplicationTTL` | `300000` | 5 minutes (5 _ 60 _ 1000 ms) |
246
+ | `cleanupDebounceMs` | `0` | No debounce by default |
247
+ | `batchingDelayMs` | `20` | Batch delay in ms (0 = off) |
248
+ | `excludedBatchMessageTypes` | `[]` | Types never batched |
245
249
 
246
250
  #### Return Value
247
251
 
@@ -484,6 +488,40 @@ function TabStatus() {
484
488
  - Implement debouncing for rapid state changes
485
489
  - Consider using `expirationDuration` for temporary messages
486
490
 
491
+ #### Batching Mechanism
492
+
493
+ **Batching** allows you to group multiple outgoing messages and send them together in a single post to the BroadcastChannel. This can significantly reduce the number of cross-tab events, improve performance, and avoid flooding the channel when many messages are sent in rapid succession (e.g., during fast typing or bulk updates).
494
+
495
+ - **batchingDelayMs**: If set to a value greater than 0 (default: 20ms), outgoing messages are collected for up to this delay and then sent as an array. If 0 or negative, batching is disabled and all messages are sent immediately.
496
+ - **excludedBatchMessageTypes**: An array of message types that should always be sent immediately, even if batching is enabled. Use this for urgent or high-priority messages (e.g., 'alert', 'sync-now').
497
+
498
+ **How it works:**
499
+
500
+ - When batching is enabled, calls to `postMessage` within the batching window are buffered and sent as a batch (array of messages) after the delay.
501
+ - On the receiving side, the hook automatically handles both single messages and batches (arrays). If you listen to the channel directly, always check if `Array.isArray(event.data)`.
502
+ - If the tab unmounts or the channel closes, any unsent batched messages are flushed immediately.
503
+
504
+ **Why batching matters:**
505
+
506
+ - Reduces the number of events and improves efficiency, especially for high-frequency updates.
507
+ - Prevents message storms that can occur when many updates happen in a short time.
508
+ - Lets you control which messages are always sent immediately for real-time needs.
509
+
510
+ **Example:**
511
+
512
+ ```tsx
513
+ const { postMessage } = useBroadcastChannel('my-channel', {
514
+ batchingDelayMs: 50, // Batch messages for up to 50ms
515
+ excludedBatchMessageTypes: ['alert'], // Always send 'alert' immediately
516
+ });
517
+
518
+ // These will be batched if sent within 50ms
519
+ postMessage('edit', { field: 'a', value: 1 });
520
+ postMessage('edit', { field: 'b', value: 2 });
521
+ // This will be sent immediately
522
+ postMessage('alert', { message: 'Something happened!' });
523
+ ```
524
+
487
525
  ### Memory Management
488
526
 
489
527
  - Clear messages when they're no longer needed using `clearReceivedMessages` / `clearSentMessages`
@@ -1,3 +1,13 @@
1
1
  import { BroadcastActions, BroadcastOptions } from '../types/types';
2
+ /**
3
+ * useBroadcastChannel hook
4
+ *
5
+ * Note: When batching is enabled (batchingDelayMs > 0), messages sent over the channel may be received as either:
6
+ * - a single BroadcastMessage (object), or
7
+ * - an array of BroadcastMessage (batch)
8
+ *
9
+ * The event handler in this hook supports both formats. If you listen to the channel directly, always check:
10
+ * if (Array.isArray(event.data)) { ... } else { ... }
11
+ */
2
12
  export declare const useBroadcastChannel: (channelName: string, options?: BroadcastOptions) => BroadcastActions;
3
13
  export default useBroadcastChannel;
package/dist/index.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var e=require("react"),r=require("react/jsx-runtime");const t="__INTERNAL__",s=()=>Math.random().toString(36).substr(2,9),n=(e,r)=>{const t=`${s()}-${e}-${r}`;return btoa(t).replace(/=+$/,"")},o=e=>!!e.expirationDate&&e.expirationDate<Date.now(),a=(e,r,t,s={})=>{var o;const a=Date.now();return{id:n(t,a),type:e,message:r,timestamp:a,source:t,expirationDate:null!==(o=s.expirationDate)&&void 0!==o?o:s.expirationDuration?a+s.expirationDuration:void 0}},c=(e,r,s="")=>{const n=btoa(`react-broadcast-sync:${e}:${`${r}-${s}`}`);return`${t}:${e}:${n}`},l=e=>e&&"object"==typeof e&&"string"==typeof e.type&&e.type.startsWith(`${t}:`)&&"string"==typeof e.source,i=(e,r,t)=>{if("undefined"==typeof process||!process.env||"true"!==process.env.REACT_APP_DEBUG_BROADCAST)return;const s=`[${(new Date).toISOString()}] [react-broadcast-sync]`;switch(e){case"info":console.log(s,r,t||"");break;case"warn":console.warn(s,r,t||"");break;case"error":console.error(s,r,t||"")}},u={created:e=>i("info","Channel created:",e),closed:e=>i("info","Channel closed:",e)},d={sent:e=>i("info","Message sent:",e),received:e=>i("info","Message received:",e),cleared:e=>i("info","Message cleared:",e),expired:e=>i("info","Message expired:",e),duplicate:e=>i("warn","Duplicate message ignored:",e),allSentCleared:()=>i("info","All sent messages cleared"),allReceivedCleared:()=>i("info","All received messages cleared"),ignored:e=>i("info","Message ignored due to type filter:",e)},p={inProgress:()=>i("warn","Ping already in progress. Skipping call.")},f={started:()=>i("info","Cleanup started"),completed:e=>i("info","Cleanup completed:",{removedCount:e})},g=e=>i("error","Error:",e),h="CLEAR_SENT_MESSAGES",v="PING",m="PONG";let y;if("test"===process.env.NODE_ENV)try{y=require("react-dom").flushSync}catch(e){}const C=(r,t={})=>{const{sourceName:n,cleaningInterval:i=1e3,keepLatestMessage:C=!1,registeredTypes:b=[],namespace:E="",deduplicationTTL:S=3e5,cleanupDebounceMs:P=0}=t,[M,w]=e.useState([]),[N,x]=e.useState([]),[B,D]=e.useState(null),[k,A]=e.useState(!1),T=e.useRef(null),$=e.useRef(new Map),_=e.useRef(null),G=e.useMemo((()=>n||`tab-${s()}`),[n]),R=e.useMemo((()=>({CLEAR_SENT_MESSAGES:c(h,r,E),PING:c(v,r,E),PONG:c(m,r,E)})),[r,E]),I=e.useMemo((()=>`${r}-${E}`),[r,E]),L=e.useMemo((()=>b),[JSON.stringify(b)]),O=e.useCallback((()=>{w((e=>e.filter((e=>!o(e)))))}),[]),j=e.useRef(P>0?((e,r)=>{let t,s=null,n=null;const o=(...o)=>{n=o,null!==s&&clearTimeout(s),s=setTimeout((()=>{s=null,null!==n&&(t=e(...n),n=null)}),r)};return o.cancel=()=>{null!==s&&(clearTimeout(s),s=null,n=null)},o.flush=()=>(null!==s&&(clearTimeout(s),s=null,null!==n&&(t=e(...n),n=null)),t),o})(O,P):Object.assign(O,{cancel:()=>{}})).current,q=e.useCallback((e=>{D(e),setTimeout((()=>D(null)),3e3)}),[]),F=e.useCallback(((e=300)=>{if(k)return p.inProgress(),Promise.resolve([]);if(!T.current){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),q(e),Promise.resolve([])}y?y((()=>A(!0))):A(!0);const r=new Set;return _.current=r,T.current.postMessage(a(R.PING,null,G)),new Promise((t=>{setTimeout((()=>{A(!1),_.current===r&&(_.current=null),t(Array.from(r))}),e)}))}),[R.PING,G,q,k,y]),J=e.useCallback(((e,r,t={})=>{const s=T.current;if(!s){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),void q(e)}try{const n=a(e,r,G,t);s.postMessage(n),d.sent(n),x((e=>[...e,n]))}catch(e){const r="Failed to send message";g(r),q(r)}}),[G,q]),U=e.useCallback(((e={})=>{const r=Boolean(e.ids&&e.ids.length||e.types&&e.types.length||e.sources&&e.sources.length);w((t=>r?t.filter((r=>!(e.ids&&e.ids.includes(r.id)||e.types&&e.types.includes(r.type)||e.sources&&e.sources.includes(r.source)))):[]))}),[]),V=e.useCallback(((e={})=>{var r,t,s;const{ids:n=[],types:o=[],sync:c=!1}=null!=e?e:{};x((e=>n.length>0||o.length>0?e.filter((e=>{if(e.source!==G)return!0;const r=0===n.length||n.includes(e.id),t=0===o.length||o.includes(e.type);return!(r&&t)})):[])),c&&(null===(r=T.current)||void 0===r||r.postMessage(a(R.CLEAR_SENT_MESSAGES,{ids:null!==(t=e.ids)&&void 0!==t?t:[],types:null!==(s=e.types)&&void 0!==s?s:[]},G)))}),[]),W=e.useCallback(((e={})=>{const{source:r,type:t}=e;for(let e=M.length-1;e>=0;e--){const s=M[e],n=!r||s.source===r,o=!t||s.type===t;if(n&&o)return s}return null}),[M]),z=e.useCallback((e=>{var r;try{const t=e.data;if(d.received(t),!(e=>Boolean(e&&"object"==typeof e&&"id"in e))(t))return;if(t.source===G)return;if(l(t)){if(t.type===R.CLEAR_SENT_MESSAGES){const{ids:e=[],types:r=[]}=t.message||{};return void w((s=>[...s.filter((s=>{if(s.source!==t.source)return!0;const n=0===e.length||e.includes(s.id),o=0===r.length||r.includes(s.type);return!(n&&o)}))]))}if(t.type===R.PING)return void(null===(r=T.current)||void 0===r||r.postMessage(a(R.PONG,null,G)));if(t.type===R.PONG){const e=t.source,r=_.current;return void(r&&!1===r.has(e)&&r.add(e))}}if(L.length>0&&!L.includes(t.type))return void d.ignored(t.type);if(o(t))return void d.expired(t.id);const s=Date.now(),n=$.current.get(t.id);if(n&&s-n<S)return void d.duplicate(t.id);$.current.set(t.id,s),w((e=>C?[t]:[...e,t]))}catch(e){const r="Error processing broadcast message";g(r),q(r)}}),[G,L,C,q,R,S]),H=e.useCallback((()=>{const e=T.current;e&&"function"==typeof e.close&&(e.removeEventListener("message",z),e.close(),u.closed(I),T.current=null)}),[z,I]);return e.useEffect((()=>{if("undefined"==typeof BroadcastChannel){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),void q(e)}const e=new BroadcastChannel(I);return T.current=e,u.created(I),e.addEventListener("message",z),()=>{H()}}),[I,z,q]),e.useEffect((()=>{if(i<=0)return;const e=setInterval((()=>{f.started();const e=M.length;j(),f.completed(e-M.length)}),i);return()=>{var r;clearInterval(e),P>0&&(null===(r=j.cancel)||void 0===r||r.call(j))}}),[i,j,P]),e.useEffect((()=>{const e=setInterval((()=>{const e=Date.now();for(const[r,t]of $.current.entries())e-t>=S&&$.current.delete(r)}),6e4);return()=>clearInterval(e)}),[S]),{channelName:I,messages:M,sentMessages:N,isPingInProgress:k,ping:F,postMessage:J,clearReceivedMessages:U,clearSentMessages:V,getLatestMessage:W,error:B,closeChannel:H}},b=e.createContext(void 0);class E extends e.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){console.error("BroadcastChannel error:",e)}render(){return this.state.hasError?r.jsx("div",{children:"Error occurred in BroadcastProvider"}):this.props.children}}exports.BroadcastProvider=({children:t,channelName:s})=>{const{messages:n,error:o}=C(s),[a,c]=e.useState(null),l=e.useRef(null);e.useEffect((()=>{if("undefined"==typeof BroadcastChannel)return void c("BroadcastChannel is not supported in this browser. Please check browser compatibility.");const e=new BroadcastChannel(s);return l.current=e,()=>{e.close()}}),[s]);const i=e.useMemo((()=>({messages:n,error:a||o,channel:l.current})),[n,a,o]);return r.jsx(E,{children:r.jsx(b.Provider,{value:i,children:t})})},exports.useBroadcastChannel=C,exports.useBroadcastProvider=()=>{const r=e.useContext(b);if(!r)throw new Error("useBroadcastProvider must be used within a BroadcastProvider");return r};
1
+ "use strict";var e=require("react"),r=require("react/jsx-runtime");const t="__INTERNAL__",s=()=>Math.random().toString(36).substr(2,9),n=(e,r)=>{const t=`${s()}-${e}-${r}`;return btoa(t).replace(/=+$/,"")},o=e=>!!e.expirationDate&&e.expirationDate<Date.now(),c=(e,r,t,s={})=>{var o;const c=Date.now();return{id:n(t,c),type:e,message:r,timestamp:c,source:t,expirationDate:null!==(o=s.expirationDate)&&void 0!==o?o:s.expirationDuration?c+s.expirationDuration:void 0}},a=(e,r,s="")=>{const n=btoa(`react-broadcast-sync:${e}:${`${r}-${s}`}`);return`${t}:${e}:${n}`},l=e=>e&&"object"==typeof e&&"string"==typeof e.type&&e.type.startsWith(`${t}:`)&&"string"==typeof e.source,u=(e,r,t)=>{if("undefined"==typeof process||!process.env||"true"!==process.env.REACT_APP_DEBUG_BROADCAST)return;const s=`[${(new Date).toISOString()}] [react-broadcast-sync]`;switch(e){case"info":console.log(s,r,t||"");break;case"warn":console.warn(s,r,t||"");break;case"error":console.error(s,r,t||"")}},i={created:e=>u("info","Channel created:",e),closed:e=>u("info","Channel closed:",e)},d={sent:e=>u("info","Message sent:",e),received:e=>u("info","Message received:",e),cleared:e=>u("info","Message cleared:",e),expired:e=>u("info","Message expired:",e),duplicate:e=>u("warn","Duplicate message ignored:",e),allSentCleared:()=>u("info","All sent messages cleared"),allReceivedCleared:()=>u("info","All received messages cleared"),ignored:e=>u("info","Message ignored due to type filter:",e)},p={inProgress:()=>u("warn","Ping already in progress. Skipping call.")},f={started:()=>u("info","Cleanup started"),completed:e=>u("info","Cleanup completed:",{removedCount:e})},g=e=>u("error","Error:",e),h="CLEAR_SENT_MESSAGES",m="PING",v="PONG";let y;if("test"===process.env.NODE_ENV)try{y=require("react-dom").flushSync}catch(e){}const C=(r,t={})=>{const{sourceName:n,cleaningInterval:u=1e3,keepLatestMessage:C=!1,registeredTypes:E=[],namespace:b="",deduplicationTTL:S=3e5,cleanupDebounceMs:M=0,batchingDelayMs:P=20,excludedBatchMessageTypes:w=[]}=t,[N,x]=e.useState([]),[B,T]=e.useState([]),[D,A]=e.useState(null),[k,R]=e.useState(!1),$=e.useRef(null),_=e.useRef(new Map),G=e.useRef(null),I=e.useRef(null),L=e.useRef([]),O=e.useRef(!1),j=e.useMemo((()=>n||`tab-${s()}`),[n]),F=e.useMemo((()=>({CLEAR_SENT_MESSAGES:a(h,r,b),PING:a(m,r,b),PONG:a(v,r,b)})),[r,b]),q=e.useMemo((()=>b?`${r}-${b}`:r),[r,b]),J=e.useMemo((()=>E),[JSON.stringify(E)]),U=e.useCallback((()=>{x((e=>e.filter((e=>!o(e)))))}),[]),V=e.useRef(M>0?((e,r)=>{let t,s=null,n=null;const o=(...o)=>{n=o,null!==s&&clearTimeout(s),s=setTimeout((()=>{s=null,null!==n&&(t=e(...n),n=null)}),r)};return o.cancel=()=>{null!==s&&(clearTimeout(s),s=null,n=null)},o.flush=()=>(null!==s&&(clearTimeout(s),s=null,null!==n&&(t=e(...n),n=null)),t),o})(U,M):Object.assign(U,{cancel:()=>{}})).current,W=e.useCallback((e=>{A(e),setTimeout((()=>A(null)),3e3)}),[]),z=e.useCallback(((e=300)=>{if(k)return p.inProgress(),Promise.resolve([]);if(!$.current){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),W(e),Promise.resolve([])}y?y((()=>R(!0))):R(!0);const r=new Set;return G.current=r,$.current.postMessage(c(F.PING,null,j)),new Promise((t=>{setTimeout((()=>{R(!1),G.current===r&&(G.current=null),t(Array.from(r))}),e)}))}),[F.PING,j,W,k,y]),H=e.useCallback(((e,r,t={})=>{const s=$.current;if(!s){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),void W(e)}const n=c(e,r,j,t);if(!P||P<0||w.includes(e))try{s.postMessage(n)}catch(e){const r="Failed to send message";g(r),W(r),O.current=!0}else L.current.push(n),I.current||(I.current=setTimeout((()=>{if(O.current)return L.current=[],void(I.current=null);try{s.postMessage(L.current)}catch(e){const r="Failed to send message";g(r),W(r),O.current=!0}L.current=[],I.current=null}),P));d.sent(n),T((e=>[...e,n]))}),[j,W,P,w]),K=e.useCallback(((e={})=>{const r=Boolean(e.ids&&e.ids.length||e.types&&e.types.length||e.sources&&e.sources.length);x((t=>r?t.filter((r=>!(e.ids&&e.ids.includes(r.id)||e.types&&e.types.includes(r.type)||e.sources&&e.sources.includes(r.source)))):[]))}),[]),Q=e.useCallback(((e={})=>{var r,t,s;const{ids:n=[],types:o=[],sync:a=!1}=null!=e?e:{};T((e=>n.length>0||o.length>0?e.filter((e=>{if(e.source!==j)return!0;const r=0===n.length||n.includes(e.id),t=0===o.length||o.includes(e.type);return!(r&&t)})):[])),a&&(null===(r=$.current)||void 0===r||r.postMessage(c(F.CLEAR_SENT_MESSAGES,{ids:null!==(t=e.ids)&&void 0!==t?t:[],types:null!==(s=e.types)&&void 0!==s?s:[]},j)))}),[]),X=e.useCallback(((e={})=>{const{source:r,type:t}=e;for(let e=N.length-1;e>=0;e--){const s=N[e],n=!r||s.source===r,o=!t||s.type===t;if(n&&o)return s}return null}),[N]),Y=e.useCallback((e=>{var r;try{const t=e.data;if(d.received(t),!(e=>Boolean(e&&"object"==typeof e&&"id"in e))(t))return;if(t.source===j)return;if(l(t)){if(t.type===F.CLEAR_SENT_MESSAGES){const{ids:e=[],types:r=[]}=t.message||{};return void x((s=>[...s.filter((s=>{if(s.source!==t.source)return!0;const n=0===e.length||e.includes(s.id),o=0===r.length||r.includes(s.type);return!(n&&o)}))]))}if(t.type===F.PING)return void(null===(r=$.current)||void 0===r||r.postMessage(c(F.PONG,null,j)));if(t.type===F.PONG){const e=t.source,r=G.current;return void(r&&!1===r.has(e)&&r.add(e))}}if(J.length>0&&!J.includes(t.type))return void d.ignored(t.type);if(o(t))return void d.expired(t.id);const s=Date.now(),n=_.current.get(t.id);if(n&&s-n<S)return void d.duplicate(t.id);_.current.set(t.id,s),x((e=>C?[t]:[...e,t]))}catch(e){const r="Error processing broadcast message";g(r),W(r)}}),[j,J,C,W,F,S]),Z=e.useCallback((()=>{const e=$.current;e&&"function"==typeof e.close&&(e.removeEventListener("message",Y),e.close(),i.closed(q),$.current=null)}),[Y,q]);return e.useEffect((()=>{if("undefined"==typeof BroadcastChannel){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return g(e),void W(e)}const e=new BroadcastChannel(q);return $.current=e,i.created(q),e.addEventListener("message",(e=>{Array.isArray(e.data)?e.data.forEach((e=>{Y({data:e})})):Y(e)})),()=>{Z()}}),[q,Y,W]),e.useEffect((()=>{if(u<=0)return;const e=setInterval((()=>{f.started();const e=N.length;V(),f.completed(e-N.length)}),u);return()=>{var r;clearInterval(e),M>0&&(null===(r=V.cancel)||void 0===r||r.call(V))}}),[u,V,M]),e.useEffect((()=>{const e=setInterval((()=>{const e=Date.now();for(const[r,t]of _.current.entries())e-t>=S&&_.current.delete(r)}),6e4);return()=>clearInterval(e)}),[S]),e.useEffect((()=>()=>{if(L.current.length>0&&$.current&&!O.current){try{$.current.postMessage(L.current)}catch(e){const r="Failed to send message";g(r),W(r)}L.current=[],setTimeout((()=>{}),0)}I.current&&(clearTimeout(I.current),I.current=null),O.current=!1}),[]),{channelName:q,messages:N,sentMessages:B,isPingInProgress:k,ping:z,postMessage:H,clearReceivedMessages:K,clearSentMessages:Q,getLatestMessage:X,error:D,closeChannel:Z}},E=e.createContext(void 0);class b extends e.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){console.error("BroadcastChannel error:",e)}render(){return this.state.hasError?r.jsx("div",{children:"Error occurred in BroadcastProvider"}):this.props.children}}exports.BroadcastProvider=({children:t,channelName:s})=>{const{messages:n,error:o}=C(s),[c,a]=e.useState(null),l=e.useRef(null);e.useEffect((()=>{if("undefined"==typeof BroadcastChannel)return void a("BroadcastChannel is not supported in this browser. Please check browser compatibility.");const e=new BroadcastChannel(s);return l.current=e,()=>{e.close()}}),[s]);const u=e.useMemo((()=>({messages:n,error:c||o,channel:l.current})),[n,c,o]);return r.jsx(b,{children:r.jsx(E.Provider,{value:u,children:t})})},exports.useBroadcastChannel=C,exports.useBroadcastProvider=()=>{const r=e.useContext(E);if(!r)throw new Error("useBroadcastProvider must be used within a BroadcastProvider");return r};
2
2
  //# sourceMappingURL=index.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs.js","sources":["../src/utils/messageUtils.ts","../src/utils/debug.ts","../src/hooks/useBroadcastChannel.ts","../src/BroadcastProvider.tsx"],"sourcesContent":[null,null,null,null],"names":["INTERNAL_PREFIX","generateRandomPart","Math","random","toString","substr","generateMessageId","source","timestamp","raw","btoa","replace","isMessageExpired","message","expirationDate","Date","now","createMessage","type","content","options","id","_a","expirationDuration","undefined","getInternalMessageType","baseType","channelName","namespace","hash","isValidInternalClearMessage","startsWith","log","level","data","process","env","REACT_APP_DEBUG_BROADCAST","prefix","toISOString","console","warn","error","debug","created","name","closed","sent","received","cleared","messageId","expired","duplicate","allSentCleared","allReceivedCleared","ignored","messageType","inProgress","started","completed","removedCount","INTERNAL_MESSAGE_TYPES","flushSyncFn","NODE_ENV","require","flushSync","useBroadcastChannel","sourceName","cleaningInterval","keepLatestMessage","registeredTypes","deduplicationTTL","cleanupDebounceMs","messages","setMessages","useState","sentMessages","setSentMessages","setError","isPingInProgress","setIsPingInProgress","channel","useRef","receivedMessageIds","Map","activeSourcesCollector","useMemo","internalTypes","CLEAR_SENT_MESSAGES","PING","PONG","resolvedChannelName","stableRegisteredTypes","JSON","stringify","performCleanup","useCallback","prev","filter","msg","debouncedCleanup","debounce","fn","wait","result","timeoutId","lastArgs","debounced","args","clearTimeout","setTimeout","cancel","flush","Object","assign","current","setErrorMessage","ping","timeoutMs","Promise","resolve","collector","Set","postMessage","Array","from","messageContent","channelCurrent","e","clearReceivedMessages","hasFilters","Boolean","ids","length","types","sources","includes","clearSentMessages","sync","idMatches","typeMatches","_b","_c","getLatestMessage","i","sourceMatches","handleMessage","event","isValidMessage","pongSource","has","add","receivedAt","get","set","closeChannel","bc","close","removeEventListener","useEffect","BroadcastChannel","addEventListener","interval","setInterval","before","clearInterval","call","entries","delete","BroadcastChannelContext","createContext","ErrorBoundary","React","Component","constructor","this","state","hasError","getDerivedStateFromError","componentDidCatch","render","_jsx","props","children","BroadcastProvider","hookError","value","Provider","useBroadcastProvider","context","useContext","Error"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs.js","sources":["../src/utils/messageUtils.ts","../src/utils/debug.ts","../src/hooks/useBroadcastChannel.ts","../src/BroadcastProvider.tsx"],"sourcesContent":[null,null,null,null],"names":["INTERNAL_PREFIX","generateRandomPart","Math","random","toString","substr","generateMessageId","source","timestamp","raw","btoa","replace","isMessageExpired","message","expirationDate","Date","now","createMessage","type","content","options","id","_a","expirationDuration","undefined","getInternalMessageType","baseType","channelName","namespace","hash","isValidInternalClearMessage","startsWith","log","level","data","process","env","REACT_APP_DEBUG_BROADCAST","prefix","toISOString","console","warn","error","debug","created","name","closed","sent","received","cleared","messageId","expired","duplicate","allSentCleared","allReceivedCleared","ignored","messageType","inProgress","started","completed","removedCount","INTERNAL_MESSAGE_TYPES","flushSyncFn","NODE_ENV","require","flushSync","useBroadcastChannel","sourceName","cleaningInterval","keepLatestMessage","registeredTypes","deduplicationTTL","cleanupDebounceMs","batchingDelayMs","excludedBatchMessageTypes","messages","setMessages","useState","sentMessages","setSentMessages","setError","isPingInProgress","setIsPingInProgress","channel","useRef","receivedMessageIds","Map","activeSourcesCollector","batchingTimeoutRef","batchingMessagesRef","batchingErrorRef","useMemo","internalTypes","CLEAR_SENT_MESSAGES","PING","PONG","resolvedChannelName","stableRegisteredTypes","JSON","stringify","performCleanup","useCallback","prev","filter","msg","debouncedCleanup","debounce","fn","wait","result","timeoutId","lastArgs","debounced","args","clearTimeout","setTimeout","cancel","flush","Object","assign","current","setErrorMessage","ping","timeoutMs","Promise","resolve","collector","Set","postMessage","Array","from","messageContent","channelCurrent","includes","e","push","clearReceivedMessages","hasFilters","Boolean","ids","length","types","sources","clearSentMessages","sync","idMatches","typeMatches","_b","_c","getLatestMessage","i","sourceMatches","handleMessage","event","isValidMessage","pongSource","has","add","receivedAt","get","set","closeChannel","bc","close","removeEventListener","useEffect","BroadcastChannel","addEventListener","isArray","forEach","interval","setInterval","before","clearInterval","call","key","entries","delete","BroadcastChannelContext","createContext","ErrorBoundary","React","Component","constructor","this","state","hasError","getDerivedStateFromError","componentDidCatch","render","_jsx","props","children","BroadcastProvider","hookError","value","Provider","useBroadcastProvider","context","useContext","Error"],"mappings":"mEAEA,MAAMA,EAAkB,eAIXC,EAAqBA,IAAMC,KAAKC,SAASC,SAAS,IAAIC,OAAO,EAAG,GAMhEC,EAAoBA,CAACC,EAAgBC,KAChD,MAAMC,EAAM,GAAGR,OAAwBM,KAAUC,IACjD,OAAOE,KAAKD,GAAKE,QAAQ,MAAO,KASrBC,EAAoBC,KACxBA,EAAQC,gBAAiBD,EAAQC,eAAiBC,KAAKC,MAInDC,EAAgBA,CAC3BC,EACAC,EACAZ,EACAa,EAAoE,CAAA,WAEpE,MAAMZ,EAAYO,KAAKC,MACvB,MAAO,CACLK,GAAIf,EAAkBC,EAAQC,GAC9BU,OACAL,QAASM,EACTX,YACAD,SACAO,eAEE,UADAM,EAAQN,sBACR,IAAAQ,EAAAA,EAACF,EAAQG,mBAAqBf,EAAYY,EAAQG,wBAAqBC,IAIhEC,EAAyBA,CACpCC,EACAC,EACAC,EAAY,MAEZ,MAEMC,EAAOnB,KADC,wBAAagB,KADP,GAAGC,KAAeC,OAGtC,MAAO,GAAG5B,KAAmB0B,KAAYG,KAO9BC,EAA+BjB,GAExCA,GACmB,iBAAZA,GACiB,iBAAjBA,EAAQK,MACAL,EAAQK,KARba,WAAW,GAAG/B,OASE,iBAAnBa,EAAQN,OCzDbyB,EAAMA,CAACC,EAAiBpB,EAAiBqB,KAC7C,GATuB,oBAAZC,UAA2BA,QAAQC,KACK,SAA1CD,QAAQC,IAAIC,0BAQD,OAEpB,MACMC,EAAS,KADG,IAAIvB,MAAOwB,wCAE7B,OAAQN,GACN,IAAK,OACHO,QAAQR,IAAIM,EAAQzB,EAASqB,GAAQ,IACrC,MACF,IAAK,OACHM,QAAQC,KAAKH,EAAQzB,EAASqB,GAAQ,IACtC,MACF,IAAK,QACHM,QAAQE,MAAMJ,EAAQzB,EAASqB,GAAQ,MAKhCS,EACF,CACPC,QAAUC,GAAiBb,EAAI,OAAQ,mBAAoBa,GAC3DC,OAASD,GAAiBb,EAAI,OAAQ,kBAAmBa,IAHhDF,EAKF,CACPI,KAAOlC,GAAiBmB,EAAI,OAAQ,gBAAiBnB,GACrDmC,SAAWnC,GAAiBmB,EAAI,OAAQ,oBAAqBnB,GAC7DoC,QAAUC,GAAsBlB,EAAI,OAAQ,mBAAoBkB,GAChEC,QAAUD,GAAsBlB,EAAI,OAAQ,mBAAoBkB,GAChEE,UAAYF,GAAsBlB,EAAI,OAAQ,6BAA8BkB,GAC5EG,eAAgBA,IAAMrB,EAAI,OAAQ,6BAClCsB,mBAAoBA,IAAMtB,EAAI,OAAQ,iCACtCuB,QAAUC,GACRxB,EAAI,OAAQ,sCAAuCwB,IAd5Cb,EAgBL,CACJc,WAAYA,IAAMzB,EAAI,OAAQ,6CAjBrBW,EAmBF,CACPe,QAASA,IAAM1B,EAAI,OAAQ,mBAC3B2B,UAAYC,GAAyB5B,EAAI,OAAQ,qBAAsB,CAAE4B,kBArBhEjB,EAuBHD,GAAkBV,EAAI,QAAS,SAAUU,GC9B7CmB,EACiB,sBADjBA,EAEE,OAFFA,EAGE,OAGR,IAAIC,EACJ,GAA6B,SAAzB3B,QAAQC,IAAI2B,SACd,IAEED,EAAcE,QAAQ,aAAaC,SACpC,CAAC,MAAA3C,GACA,CAcG,MAAM4C,EAAsBA,CACjCvC,EACAP,EAA4B,MAE5B,MAAM+C,WACJA,EAAUC,iBACVA,EAAmB,IAAIC,kBACvBA,GAAoB,EAAKC,gBACzBA,EAAkB,GAAE1C,UACpBA,EAAY,GAAE2C,iBACdA,EAAmB,IAAaC,kBAChCA,EAAoB,EAACC,gBACrBA,EAAkB,GAAEC,0BACpBA,EAA4B,IAC1BtD,GAGGuD,EAAUC,GAAeC,EAAAA,SAA6B,KACtDC,EAAcC,GAAmBF,EAAAA,SAA6B,KAC9DnC,EAAOsC,GAAYH,EAAAA,SAAwB,OAC3CI,EAAkBC,GAAuBL,EAAAA,UAAS,GAGnDM,EAAUC,EAAMA,OAA0B,MAC1CC,EAAqBD,EAAAA,OAAO,IAAIE,KAChCC,EAAyBH,EAAMA,OAAqB,MACpDI,EAAqBJ,EAAMA,OAAwB,MACnDK,EAAsBL,EAAMA,OAAqB,IACjDM,EAAmBN,EAAMA,QAAC,GAG1B7E,EAASoF,EAAAA,SAAQ,IAAMxB,GFtES,OAAOlE,OEsEoB,CAACkE,IAC5DyB,EAAgBD,EAAAA,SACpB,KAAO,CACLE,oBAAqBpE,EACnBoC,EACAlC,EACAC,GAEFkE,KAAMrE,EAAuBoC,EAA6BlC,EAAaC,GACvEmE,KAAMtE,EAAuBoC,EAA6BlC,EAAaC,MAEzE,CAACD,EAAaC,IAGVoE,EAAsBL,EAAAA,SAAQ,IAE3B/D,EAAY,GAAGD,KAAeC,IAAcD,GAClD,CAACA,EAAaC,IAEXqE,EAAwBN,EAAOA,SAAC,IAAMrB,GAAiB,CAAC4B,KAAKC,UAAU7B,KAEvE8B,EAAiBC,EAAAA,aAAY,KACjCzB,GAAY0B,GAAQA,EAAKC,QAAOC,IAAQ5F,EAAiB4F,SACxD,IAEGC,EAAmBrB,EAAAA,OAIvBZ,EAAoB,EFpCAkC,EACtBC,EACAC,KAKA,IAEIC,EAFAC,EAAkD,KAClDC,EAAiC,KAGrC,MAAMC,EAAYA,IAAIC,KACpBF,EAAWE,EACO,OAAdH,GACFI,aAAaJ,GAEfA,EAAYK,YAAW,KACrBL,EAAY,KACK,OAAbC,IACFF,EAASF,KAAMI,GACfA,EAAW,QAEZH,IAuBL,OApBAI,EAAUI,OAAS,KACC,OAAdN,IACFI,aAAaJ,GACbA,EAAY,KACZC,EAAW,OAIfC,EAAUK,MAAQ,KACE,OAAdP,IACFI,aAAaJ,GACbA,EAAY,KACK,OAAbC,IACFF,EAASF,KAAMI,GACfA,EAAW,OAGRF,GAGFG,GERDN,CAASN,EAAgB5B,GACzB8C,OAAOC,OAAOnB,EAAgB,CAAEgB,OAAQA,UAC5CI,QAEIC,EAAkBpB,EAAWA,aAAE3D,IACnCsC,EAAStC,GACTyE,YAAW,IAAMnC,EAAS,OAAO,OAChC,IAEG0C,EAAOrB,EAAAA,aACX,CAACsB,EAAoB,OACnB,GAAI1C,EAEF,OADAtC,EAAWc,aACJmE,QAAQC,QAAQ,IAGzB,IAAK1C,EAAQqC,QAAS,CACpB,MAAM9E,EACJ,yFAGF,OAFAC,EAAYD,GACZ+E,EAAgB/E,GACTkF,QAAQC,QAAQ,GACzB,CAGI/D,EACFA,GAAY,IAAMoB,GAAoB,KAEtCA,GAAoB,GAEtB,MAAM4C,EAAY,IAAIC,IAKtB,OAJAxC,EAAuBiC,QAAUM,EAEjC3C,EAAQqC,QAAQQ,YAAY/G,EAAc2E,EAAcE,KAAM,KAAMvF,IAE7D,IAAIqH,SAAQC,IACjBV,YAAW,KACTjC,GAAoB,GAChBK,EAAuBiC,UAAYM,IACrCvC,EAAuBiC,QAAU,MAEnCK,EAAQI,MAAMC,KAAKJ,MAClBH,QAGP,CAAC/B,EAAcE,KAAMvF,EAAQkH,EAAiBxC,EAAkBnB,IAG5DkE,EAAc3B,EAAAA,aAClB,CAAC7C,EAAqB2E,EAAqB/G,EAA8B,MACvE,MAAMgH,EAAiBjD,EAAQqC,QAC/B,IAAKY,EAAgB,CACnB,MAAM1F,EACJ,yFAGF,OAFAC,EAAYD,QACZ+E,EAAgB/E,EAElB,CAEA,MAAM7B,EAAUI,EAAcuC,EAAa2E,EAAgB5H,EAAQa,GAInE,IADGqD,GAAmBA,EAAkB,GAAKC,EAA0B2D,SAAS7E,GAE9E,IACE4E,EAAeJ,YAAYnH,EAC5B,CAAC,MAAOyH,GACP,MAAM5F,EAAQ,yBACdC,EAAYD,GACZ+E,EAAgB/E,GAChBgD,EAAiB8B,SAAU,CAC7B,MAEA/B,EAAoB+B,QAAQe,KAAK1H,GAC5B2E,EAAmBgC,UACtBhC,EAAmBgC,QAAUL,YAAW,KACtC,GAAIzB,EAAiB8B,QAGnB,OAFA/B,EAAoB+B,QAAU,QAC9BhC,EAAmBgC,QAAU,MAG/B,IACEY,EAAeJ,YAAYvC,EAAoB+B,QAChD,CAAC,MAAOc,GACP,MAAM5F,EAAQ,yBACdC,EAAYD,GACZ+E,EAAgB/E,GAChBgD,EAAiB8B,SAAU,CAC7B,CACA/B,EAAoB+B,QAAU,GAC9BhC,EAAmBgC,QAAU,OAC5B/C,IAGP9B,EAAcI,KAAKlC,GACnBkE,GAAgBuB,GAAQ,IAAIA,EAAMzF,OAEpC,CAACN,EAAQkH,EAAiBhD,EAAiBC,IAGvC8D,EAAwBnC,EAAAA,aAAY,CAACjF,EAAwC,CAAA,KACjF,MAAMqH,EAAaC,QAChBtH,EAAQuH,KAAOvH,EAAQuH,IAAIC,QACzBxH,EAAQyH,OAASzH,EAAQyH,MAAMD,QAC/BxH,EAAQ0H,SAAW1H,EAAQ0H,QAAQF,QAGxChE,GAAY0B,GACVmC,EACInC,EAAKC,QACHC,KACIpF,EAAQuH,KAAOvH,EAAQuH,IAAIN,SAAS7B,EAAInF,KACxCD,EAAQyH,OAASzH,EAAQyH,MAAMR,SAAS7B,EAAItF,OAC5CE,EAAQ0H,SAAW1H,EAAQ0H,QAAQT,SAAS7B,EAAIjG,WAEtD,OAEL,IAEGwI,EAAoB1C,EAAAA,aAAY,CAACjF,EAAoC,CAAA,eACzE,MAAMuH,IAAEA,EAAM,GAAEE,MAAEA,EAAQ,GAAEG,KAAEA,GAAO,GAAU5H,QAAAA,EAAW,CAAE,EAC5D2D,GAAgBuB,GACdqC,EAAIC,OAAS,GAAKC,EAAMD,OAAS,EAC7BtC,EAAKC,QAAOC,IAEV,GAAIA,EAAIjG,SAAWA,EAAQ,OAAO,EAKlC,MAAM0I,EAA2B,IAAfN,EAAIC,QAAgBD,EAAIN,SAAS7B,EAAInF,IACjD6H,EAA+B,IAAjBL,EAAMD,QAAgBC,EAAMR,SAAS7B,EAAItF,MAG7D,QAAS+H,GAAaC,MAExB,KAEFF,IACa,QAAf1H,EAAA6D,EAAQqC,eAAO,IAAAlG,GAAAA,EAAE0G,YACf/G,EACE2E,EAAcC,oBACd,CAAE8C,YAAKQ,EAAA/H,EAAQuH,mBAAO,GAAIE,MAAoB,UAAbzH,EAAQyH,aAAK,IAAAO,EAAAA,EAAI,IAClD7I,OAIL,IAEG8I,EAAmBhD,EAAAA,aACvB,CAACjF,EAAmC,CAAA,KAClC,MAAMb,OAAEA,EAAMW,KAAEA,GAASE,EAEzB,IAAK,IAAIkI,EAAI3E,EAASiE,OAAS,EAAGU,GAAK,EAAGA,IAAK,CAC7C,MAAM9C,EAAM7B,EAAS2E,GACfC,GAAiBhJ,GAAUiG,EAAIjG,SAAWA,EAC1C2I,GAAehI,GAAQsF,EAAItF,OAASA,EAC1C,GAAIqI,GAAiBL,EACnB,OAAO1C,CAEX,CAEA,OAAO,OAET,CAAC7B,IAGG6E,EAAgBnD,EAAWA,aAC9BoD,UACC,IACE,MAAM5I,EAA4B4I,EAAMvH,KAGxC,GAFAS,EAAcK,SAASnC,IFtQAA,IACtB6H,QAAQ7H,GAA8B,iBAAZA,GAAwB,OAAQA,GEuQtD6I,CAAe7I,GAAU,OAC9B,GAAIA,EAAQN,SAAWA,EAAQ,OAC/B,GAAIuB,EAA4BjB,GAAU,CACxC,GAAIA,EAAQK,OAAS0E,EAAcC,oBAAqB,CACtD,MAAM8C,IAAEA,EAAM,GAAEE,MAAEA,EAAQ,IAAQhI,EAAgBA,SAAW,CAAE,EAiB/D,YAfA+D,GAAY0B,GAAQ,IACfA,EAAKC,QAAOC,IAEb,GAAIA,EAAIjG,SAAWM,EAAQN,OAAQ,OAAO,EAK1C,MAAM0I,EAA2B,IAAfN,EAAIC,QAAgBD,EAAIN,SAAS7B,EAAInF,IACjD6H,EAA+B,IAAjBL,EAAMD,QAAgBC,EAAMR,SAAS7B,EAAItF,MAE7D,QAAS+H,GAAaC,QAK5B,CACA,GAAIrI,EAAQK,OAAS0E,EAAcE,KAEjC,YADiB,QAAjBxE,EAAA6D,EAAQqC,eAAS,IAAAlG,GAAAA,EAAA0G,YAAY/G,EAAc2E,EAAcG,KAAM,KAAMxF,KAIvE,GAAIM,EAAQK,OAAS0E,EAAcG,KAAM,CACvC,MAAM4D,EAAa9I,EAAQN,OACrBuH,EAAYvC,EAAuBiC,QAMzC,YAJIM,IAA2C,IAA9BA,EAAU8B,IAAID,IAC7B7B,EAAU+B,IAAIF,GAIlB,CACF,CACA,GAAI1D,EAAsB2C,OAAS,IAAM3C,EAAsBoC,SAASxH,EAAQK,MAE9E,YADAyB,EAAcY,QAAQ1C,EAAQK,MAGhC,GAAIN,EAAiBC,GAEnB,YADA8B,EAAcQ,QAAQtC,EAAQQ,IAIhC,MAAML,EAAMD,KAAKC,MACX8I,EAAazE,EAAmBmC,QAAQuC,IAAIlJ,EAAQQ,IAC1D,GAAIyI,GAAc9I,EAAM8I,EAAavF,EAEnC,YADA5B,EAAcS,UAAUvC,EAAQQ,IAIlCgE,EAAmBmC,QAAQwC,IAAInJ,EAAQQ,GAAIL,GAC3C4D,GAAY0B,GAASjC,EAAoB,CAACxD,GAAW,IAAIyF,EAAMzF,IAChE,CAAC,MAAOyH,GACP,MAAM5F,EAAQ,qCACdC,EAAYD,GACZ+E,EAAgB/E,EAClB,IAEF,CACEnC,EACA0F,EACA5B,EACAoD,EACA7B,EACArB,IAIE0F,EAAe5D,EAAAA,aAAY,KAC/B,MAAM6D,EAAK/E,EAAQqC,QACf0C,GAA0B,mBAAbA,EAAGC,QAClBD,EAAGE,oBAAoB,UAAWZ,GAClCU,EAAGC,QACHxH,EAAcG,OAAOkD,GACrBb,EAAQqC,QAAU,QAEnB,CAACgC,EAAexD,IAqFnB,OAnFAqE,EAAAA,WAAU,KACR,GAAgC,oBAArBC,iBAAkC,CAC3C,MAAM5H,EACJ,yFAGF,OAFAC,EAAYD,QACZ+E,EAAgB/E,EAElB,CAEA,MAAMwH,EAAK,IAAII,iBAAiBtE,GAchC,OAbAb,EAAQqC,QAAU0C,EAClBvH,EAAcC,QAAQoD,GAEtBkE,EAAGK,iBAAiB,WAAYd,IAE1BxB,MAAMuC,QAAQf,EAAMvH,MACtBuH,EAAMvH,KAAKuI,SAAS5J,IAClB2I,EAAc,CAAEtH,KAAMrB,OAGxB2I,EAAcC,MAGX,KACLQ,OAED,CAACjE,EAAqBwD,EAAe/B,IAExC4C,EAAAA,WAAU,KACR,GAAIjG,GAAoB,EAAG,OAE3B,MAAMsG,EAAWC,aAAY,KAC3BhI,EAAce,UACd,MAAMkH,EAASjG,EAASiE,OACxBnC,IACA9D,EAAcgB,UAAUiH,EAASjG,EAASiE,UACzCxE,GAEH,MAAO,WACLyG,cAAcH,GAEVlG,EAAoB,IACC,QAAvBlD,EAAAmF,EAAiBW,cAAM,IAAA9F,GAAAA,EAAAwJ,KAAArE,OAG1B,CAACrC,EAAkBqC,EAAkBjC,IAExC6F,EAAAA,WAAU,KACR,MAAMK,EAAWC,aAAY,KAC3B,MAAM3J,EAAMD,KAAKC,MACjB,IAAK,MAAO+J,EAAKvK,KAAc6E,EAAmBmC,QAAQwD,UACpDhK,EAAMR,GAAa+D,GACrBc,EAAmBmC,QAAQyD,OAAOF,KAGrC,KAEH,MAAO,IAAMF,cAAcH,KAC1B,CAACnG,IAEJ8F,EAAAA,WAAU,IACD,KAEL,GAAI5E,EAAoB+B,QAAQoB,OAAS,GAAKzD,EAAQqC,UAAY9B,EAAiB8B,QAAS,CAC1F,IACErC,EAAQqC,QAAQQ,YAAYvC,EAAoB+B,QACjD,CAAC,MAAOc,GACP,MAAM5F,EAAQ,yBACdC,EAAYD,GACZ+E,EAAgB/E,EAClB,CACA+C,EAAoB+B,QAAU,GAE9BL,YAAW,QAAU,EACvB,CACI3B,EAAmBgC,UACrBN,aAAa1B,EAAmBgC,SAChChC,EAAmBgC,QAAU,MAE/B9B,EAAiB8B,SAAU,IAE5B,IAEI,CACL7F,YAAaqE,EACbrB,WACAG,eACAG,mBACAyC,OACAM,cACAQ,wBACAO,oBACAM,mBACA3G,QACAuH,iBCjcEiB,EAA0BC,EAAaA,mBAAoC3J,GAMjF,MAAM4J,UAAsBC,EAAMC,UAAlCC,WAAAA,uBACEC,KAAAC,MAAQ,CAAEC,UAAU,EAgBtB,CAdE,+BAAOC,GACL,MAAO,CAAED,UAAU,EACrB,CAEAE,iBAAAA,CAAkBlJ,GAChBF,QAAQE,MAAM,0BAA2BA,EAC3C,CAEAmJ,MAAAA,GACE,OAAIL,KAAKC,MAAMC,SACNI,EAAAA,4DAEFN,KAAKO,MAAMC,QACpB,4BAQiEC,EAAGD,WAAUrK,kBAC9E,MAAMgD,SAAEA,EAAUjC,MAAOwJ,GAAchI,EAAoBvC,IAEpDe,EAAOsC,GAAYqG,EAAMxG,SAAwB,MAClDM,EAAUC,EAAMA,OAA0B,MAEhDiF,EAAAA,WAAU,KACR,GAAgC,oBAArBC,iBAIT,YAHAtF,EACE,0FAIJ,MAAMkF,EAAK,IAAII,iBAAiB3I,GAGhC,OAFAwD,EAAQqC,QAAU0C,EAEX,KACLA,EAAGC,WAEJ,CAACxI,IAEJ,MAAMwK,EAAQxG,EAAAA,SACZ,KAAO,CAAEhB,WAAUjC,MAAOA,GAASwJ,EAAW/G,QAASA,EAAQqC,WAC/D,CAAC7C,EAAUjC,EAAOwJ,IAGpB,OACEJ,EAAAA,IAACV,EACC,CAAAY,SAAAF,EAAAA,IAACZ,EAAwBkB,SAAS,CAAAD,MAAOA,EAAKH,SAAGA,kEAKnBK,KAClC,MAAMC,EAAUC,EAAUA,WAACrB,GAC3B,IAAKoB,EACH,MAAM,IAAIE,MAAM,gEAElB,OAAOF"}
package/dist/index.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- import e,{useState as r,useRef as t,useMemo as n,useCallback as s,useEffect as o,createContext as c,useContext as i}from"react";import{jsx as a}from"react/jsx-runtime";const l="__INTERNAL__",u=()=>Math.random().toString(36).substr(2,9),d=(e,r)=>{const t=`${u()}-${e}-${r}`;return btoa(t).replace(/=+$/,"")},p=e=>!!e.expirationDate&&e.expirationDate<Date.now(),g=(e,r,t,n={})=>{var s;const o=Date.now();return{id:d(t,o),type:e,message:r,timestamp:o,source:t,expirationDate:null!==(s=n.expirationDate)&&void 0!==s?s:n.expirationDuration?o+n.expirationDuration:void 0}},f=(e,r,t="")=>{const n=btoa(`react-broadcast-sync:${e}:${`${r}-${t}`}`);return`${l}:${e}:${n}`},h=e=>e&&"object"==typeof e&&"string"==typeof e.type&&e.type.startsWith(`${l}:`)&&"string"==typeof e.source,m=(e,r,t)=>{if("undefined"==typeof process||!process.env||"true"!==process.env.REACT_APP_DEBUG_BROADCAST)return;const n=`[${(new Date).toISOString()}] [react-broadcast-sync]`;switch(e){case"info":console.log(n,r,t||"");break;case"warn":console.warn(n,r,t||"");break;case"error":console.error(n,r,t||"")}},v={created:e=>m("info","Channel created:",e),closed:e=>m("info","Channel closed:",e)},y={sent:e=>m("info","Message sent:",e),received:e=>m("info","Message received:",e),cleared:e=>m("info","Message cleared:",e),expired:e=>m("info","Message expired:",e),duplicate:e=>m("warn","Duplicate message ignored:",e),allSentCleared:()=>m("info","All sent messages cleared"),allReceivedCleared:()=>m("info","All received messages cleared"),ignored:e=>m("info","Message ignored due to type filter:",e)},E={inProgress:()=>m("warn","Ping already in progress. Skipping call.")},S={started:()=>m("info","Cleanup started"),completed:e=>m("info","Cleanup completed:",{removedCount:e})},P=e=>m("error","Error:",e),b="CLEAR_SENT_MESSAGES",w="PING",C="PONG";let M;if("test"===process.env.NODE_ENV)try{M=require("react-dom").flushSync}catch(e){}const N=(e,c={})=>{const{sourceName:i,cleaningInterval:a=1e3,keepLatestMessage:l=!1,registeredTypes:d=[],namespace:m="",deduplicationTTL:N=3e5,cleanupDebounceMs:D=0}=c,[A,B]=r([]),[T,$]=r([]),[_,G]=r(null),[I,x]=r(!1),L=t(null),O=t(new Map),R=t(null),k=n((()=>i||`tab-${u()}`),[i]),j=n((()=>({CLEAR_SENT_MESSAGES:f(b,e,m),PING:f(w,e,m),PONG:f(C,e,m)})),[e,m]),F=n((()=>`${e}-${m}`),[e,m]),q=n((()=>d),[JSON.stringify(d)]),J=s((()=>{B((e=>e.filter((e=>!p(e)))))}),[]),U=t(D>0?((e,r)=>{let t,n=null,s=null;const o=(...o)=>{s=o,null!==n&&clearTimeout(n),n=setTimeout((()=>{n=null,null!==s&&(t=e(...s),s=null)}),r)};return o.cancel=()=>{null!==n&&(clearTimeout(n),n=null,s=null)},o.flush=()=>(null!==n&&(clearTimeout(n),n=null,null!==s&&(t=e(...s),s=null)),t),o})(J,D):Object.assign(J,{cancel:()=>{}})).current,V=s((e=>{G(e),setTimeout((()=>G(null)),3e3)}),[]),W=s(((e=300)=>{if(I)return E.inProgress(),Promise.resolve([]);if(!L.current){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return P(e),V(e),Promise.resolve([])}M?M((()=>x(!0))):x(!0);const r=new Set;return R.current=r,L.current.postMessage(g(j.PING,null,k)),new Promise((t=>{setTimeout((()=>{x(!1),R.current===r&&(R.current=null),t(Array.from(r))}),e)}))}),[j.PING,k,V,I,M]),z=s(((e,r,t={})=>{const n=L.current;if(!n){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return P(e),void V(e)}try{const s=g(e,r,k,t);n.postMessage(s),y.sent(s),$((e=>[...e,s]))}catch(e){const r="Failed to send message";P(r),V(r)}}),[k,V]),H=s(((e={})=>{const r=Boolean(e.ids&&e.ids.length||e.types&&e.types.length||e.sources&&e.sources.length);B((t=>r?t.filter((r=>!(e.ids&&e.ids.includes(r.id)||e.types&&e.types.includes(r.type)||e.sources&&e.sources.includes(r.source)))):[]))}),[]),K=s(((e={})=>{var r,t,n;const{ids:s=[],types:o=[],sync:c=!1}=null!=e?e:{};$((e=>s.length>0||o.length>0?e.filter((e=>{if(e.source!==k)return!0;const r=0===s.length||s.includes(e.id),t=0===o.length||o.includes(e.type);return!(r&&t)})):[])),c&&(null===(r=L.current)||void 0===r||r.postMessage(g(j.CLEAR_SENT_MESSAGES,{ids:null!==(t=e.ids)&&void 0!==t?t:[],types:null!==(n=e.types)&&void 0!==n?n:[]},k)))}),[]),Q=s(((e={})=>{const{source:r,type:t}=e;for(let e=A.length-1;e>=0;e--){const n=A[e],s=!r||n.source===r,o=!t||n.type===t;if(s&&o)return n}return null}),[A]),X=s((e=>{var r;try{const t=e.data;if(y.received(t),!(e=>Boolean(e&&"object"==typeof e&&"id"in e))(t))return;if(t.source===k)return;if(h(t)){if(t.type===j.CLEAR_SENT_MESSAGES){const{ids:e=[],types:r=[]}=t.message||{};return void B((n=>[...n.filter((n=>{if(n.source!==t.source)return!0;const s=0===e.length||e.includes(n.id),o=0===r.length||r.includes(n.type);return!(s&&o)}))]))}if(t.type===j.PING)return void(null===(r=L.current)||void 0===r||r.postMessage(g(j.PONG,null,k)));if(t.type===j.PONG){const e=t.source,r=R.current;return void(r&&!1===r.has(e)&&r.add(e))}}if(q.length>0&&!q.includes(t.type))return void y.ignored(t.type);if(p(t))return void y.expired(t.id);const n=Date.now(),s=O.current.get(t.id);if(s&&n-s<N)return void y.duplicate(t.id);O.current.set(t.id,n),B((e=>l?[t]:[...e,t]))}catch(e){const r="Error processing broadcast message";P(r),V(r)}}),[k,q,l,V,j,N]),Y=s((()=>{const e=L.current;e&&"function"==typeof e.close&&(e.removeEventListener("message",X),e.close(),v.closed(F),L.current=null)}),[X,F]);return o((()=>{if("undefined"==typeof BroadcastChannel){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return P(e),void V(e)}const e=new BroadcastChannel(F);return L.current=e,v.created(F),e.addEventListener("message",X),()=>{Y()}}),[F,X,V]),o((()=>{if(a<=0)return;const e=setInterval((()=>{S.started();const e=A.length;U(),S.completed(e-A.length)}),a);return()=>{var r;clearInterval(e),D>0&&(null===(r=U.cancel)||void 0===r||r.call(U))}}),[a,U,D]),o((()=>{const e=setInterval((()=>{const e=Date.now();for(const[r,t]of O.current.entries())e-t>=N&&O.current.delete(r)}),6e4);return()=>clearInterval(e)}),[N]),{channelName:F,messages:A,sentMessages:T,isPingInProgress:I,ping:W,postMessage:z,clearReceivedMessages:H,clearSentMessages:K,getLatestMessage:Q,error:_,closeChannel:Y}},D=c(void 0);class A extends e.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){console.error("BroadcastChannel error:",e)}render(){return this.state.hasError?a("div",{children:"Error occurred in BroadcastProvider"}):this.props.children}}const B=({children:r,channelName:s})=>{const{messages:c,error:i}=N(s),[l,u]=e.useState(null),d=t(null);o((()=>{if("undefined"==typeof BroadcastChannel)return void u("BroadcastChannel is not supported in this browser. Please check browser compatibility.");const e=new BroadcastChannel(s);return d.current=e,()=>{e.close()}}),[s]);const p=n((()=>({messages:c,error:l||i,channel:d.current})),[c,l,i]);return a(A,{children:a(D.Provider,{value:p,children:r})})},T=()=>{const e=i(D);if(!e)throw new Error("useBroadcastProvider must be used within a BroadcastProvider");return e};export{B as BroadcastProvider,N as useBroadcastChannel,T as useBroadcastProvider};
1
+ import e,{useState as r,useRef as t,useMemo as n,useCallback as s,useEffect as o,createContext as c,useContext as a}from"react";import{jsx as i}from"react/jsx-runtime";const l="__INTERNAL__",u=()=>Math.random().toString(36).substr(2,9),d=(e,r)=>{const t=`${u()}-${e}-${r}`;return btoa(t).replace(/=+$/,"")},p=e=>!!e.expirationDate&&e.expirationDate<Date.now(),g=(e,r,t,n={})=>{var s;const o=Date.now();return{id:d(t,o),type:e,message:r,timestamp:o,source:t,expirationDate:null!==(s=n.expirationDate)&&void 0!==s?s:n.expirationDuration?o+n.expirationDuration:void 0}},h=(e,r,t="")=>{const n=btoa(`react-broadcast-sync:${e}:${`${r}-${t}`}`);return`${l}:${e}:${n}`},f=e=>e&&"object"==typeof e&&"string"==typeof e.type&&e.type.startsWith(`${l}:`)&&"string"==typeof e.source,m=(e,r,t)=>{if("undefined"==typeof process||!process.env||"true"!==process.env.REACT_APP_DEBUG_BROADCAST)return;const n=`[${(new Date).toISOString()}] [react-broadcast-sync]`;switch(e){case"info":console.log(n,r,t||"");break;case"warn":console.warn(n,r,t||"");break;case"error":console.error(n,r,t||"")}},y={created:e=>m("info","Channel created:",e),closed:e=>m("info","Channel closed:",e)},v={sent:e=>m("info","Message sent:",e),received:e=>m("info","Message received:",e),cleared:e=>m("info","Message cleared:",e),expired:e=>m("info","Message expired:",e),duplicate:e=>m("warn","Duplicate message ignored:",e),allSentCleared:()=>m("info","All sent messages cleared"),allReceivedCleared:()=>m("info","All received messages cleared"),ignored:e=>m("info","Message ignored due to type filter:",e)},E={inProgress:()=>m("warn","Ping already in progress. Skipping call.")},S={started:()=>m("info","Cleanup started"),completed:e=>m("info","Cleanup completed:",{removedCount:e})},b=e=>m("error","Error:",e),P="CLEAR_SENT_MESSAGES",w="PING",M="PONG";let C;if("test"===process.env.NODE_ENV)try{C=require("react-dom").flushSync}catch(e){}const N=(e,c={})=>{const{sourceName:a,cleaningInterval:i=1e3,keepLatestMessage:l=!1,registeredTypes:d=[],namespace:m="",deduplicationTTL:N=3e5,cleanupDebounceMs:T=0,batchingDelayMs:D=20,excludedBatchMessageTypes:A=[]}=c,[B,$]=r([]),[_,G]=r([]),[x,I]=r(null),[L,O]=r(!1),R=t(null),k=t(new Map),j=t(null),F=t(null),q=t([]),J=t(!1),U=n((()=>a||`tab-${u()}`),[a]),V=n((()=>({CLEAR_SENT_MESSAGES:h(P,e,m),PING:h(w,e,m),PONG:h(M,e,m)})),[e,m]),W=n((()=>m?`${e}-${m}`:e),[e,m]),z=n((()=>d),[JSON.stringify(d)]),H=s((()=>{$((e=>e.filter((e=>!p(e)))))}),[]),K=t(T>0?((e,r)=>{let t,n=null,s=null;const o=(...o)=>{s=o,null!==n&&clearTimeout(n),n=setTimeout((()=>{n=null,null!==s&&(t=e(...s),s=null)}),r)};return o.cancel=()=>{null!==n&&(clearTimeout(n),n=null,s=null)},o.flush=()=>(null!==n&&(clearTimeout(n),n=null,null!==s&&(t=e(...s),s=null)),t),o})(H,T):Object.assign(H,{cancel:()=>{}})).current,Q=s((e=>{I(e),setTimeout((()=>I(null)),3e3)}),[]),X=s(((e=300)=>{if(L)return E.inProgress(),Promise.resolve([]);if(!R.current){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return b(e),Q(e),Promise.resolve([])}C?C((()=>O(!0))):O(!0);const r=new Set;return j.current=r,R.current.postMessage(g(V.PING,null,U)),new Promise((t=>{setTimeout((()=>{O(!1),j.current===r&&(j.current=null),t(Array.from(r))}),e)}))}),[V.PING,U,Q,L,C]),Y=s(((e,r,t={})=>{const n=R.current;if(!n){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return b(e),void Q(e)}const s=g(e,r,U,t);if(!D||D<0||A.includes(e))try{n.postMessage(s)}catch(e){const r="Failed to send message";b(r),Q(r),J.current=!0}else q.current.push(s),F.current||(F.current=setTimeout((()=>{if(J.current)return q.current=[],void(F.current=null);try{n.postMessage(q.current)}catch(e){const r="Failed to send message";b(r),Q(r),J.current=!0}q.current=[],F.current=null}),D));v.sent(s),G((e=>[...e,s]))}),[U,Q,D,A]),Z=s(((e={})=>{const r=Boolean(e.ids&&e.ids.length||e.types&&e.types.length||e.sources&&e.sources.length);$((t=>r?t.filter((r=>!(e.ids&&e.ids.includes(r.id)||e.types&&e.types.includes(r.type)||e.sources&&e.sources.includes(r.source)))):[]))}),[]),ee=s(((e={})=>{var r,t,n;const{ids:s=[],types:o=[],sync:c=!1}=null!=e?e:{};G((e=>s.length>0||o.length>0?e.filter((e=>{if(e.source!==U)return!0;const r=0===s.length||s.includes(e.id),t=0===o.length||o.includes(e.type);return!(r&&t)})):[])),c&&(null===(r=R.current)||void 0===r||r.postMessage(g(V.CLEAR_SENT_MESSAGES,{ids:null!==(t=e.ids)&&void 0!==t?t:[],types:null!==(n=e.types)&&void 0!==n?n:[]},U)))}),[]),re=s(((e={})=>{const{source:r,type:t}=e;for(let e=B.length-1;e>=0;e--){const n=B[e],s=!r||n.source===r,o=!t||n.type===t;if(s&&o)return n}return null}),[B]),te=s((e=>{var r;try{const t=e.data;if(v.received(t),!(e=>Boolean(e&&"object"==typeof e&&"id"in e))(t))return;if(t.source===U)return;if(f(t)){if(t.type===V.CLEAR_SENT_MESSAGES){const{ids:e=[],types:r=[]}=t.message||{};return void $((n=>[...n.filter((n=>{if(n.source!==t.source)return!0;const s=0===e.length||e.includes(n.id),o=0===r.length||r.includes(n.type);return!(s&&o)}))]))}if(t.type===V.PING)return void(null===(r=R.current)||void 0===r||r.postMessage(g(V.PONG,null,U)));if(t.type===V.PONG){const e=t.source,r=j.current;return void(r&&!1===r.has(e)&&r.add(e))}}if(z.length>0&&!z.includes(t.type))return void v.ignored(t.type);if(p(t))return void v.expired(t.id);const n=Date.now(),s=k.current.get(t.id);if(s&&n-s<N)return void v.duplicate(t.id);k.current.set(t.id,n),$((e=>l?[t]:[...e,t]))}catch(e){const r="Error processing broadcast message";b(r),Q(r)}}),[U,z,l,Q,V,N]),ne=s((()=>{const e=R.current;e&&"function"==typeof e.close&&(e.removeEventListener("message",te),e.close(),y.closed(W),R.current=null)}),[te,W]);return o((()=>{if("undefined"==typeof BroadcastChannel){const e="BroadcastChannel is not supported in this browser. Please check browser compatibility.";return b(e),void Q(e)}const e=new BroadcastChannel(W);return R.current=e,y.created(W),e.addEventListener("message",(e=>{Array.isArray(e.data)?e.data.forEach((e=>{te({data:e})})):te(e)})),()=>{ne()}}),[W,te,Q]),o((()=>{if(i<=0)return;const e=setInterval((()=>{S.started();const e=B.length;K(),S.completed(e-B.length)}),i);return()=>{var r;clearInterval(e),T>0&&(null===(r=K.cancel)||void 0===r||r.call(K))}}),[i,K,T]),o((()=>{const e=setInterval((()=>{const e=Date.now();for(const[r,t]of k.current.entries())e-t>=N&&k.current.delete(r)}),6e4);return()=>clearInterval(e)}),[N]),o((()=>()=>{if(q.current.length>0&&R.current&&!J.current){try{R.current.postMessage(q.current)}catch(e){const r="Failed to send message";b(r),Q(r)}q.current=[],setTimeout((()=>{}),0)}F.current&&(clearTimeout(F.current),F.current=null),J.current=!1}),[]),{channelName:W,messages:B,sentMessages:_,isPingInProgress:L,ping:X,postMessage:Y,clearReceivedMessages:Z,clearSentMessages:ee,getLatestMessage:re,error:x,closeChannel:ne}},T=c(void 0);class D extends e.Component{constructor(){super(...arguments),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){console.error("BroadcastChannel error:",e)}render(){return this.state.hasError?i("div",{children:"Error occurred in BroadcastProvider"}):this.props.children}}const A=({children:r,channelName:s})=>{const{messages:c,error:a}=N(s),[l,u]=e.useState(null),d=t(null);o((()=>{if("undefined"==typeof BroadcastChannel)return void u("BroadcastChannel is not supported in this browser. Please check browser compatibility.");const e=new BroadcastChannel(s);return d.current=e,()=>{e.close()}}),[s]);const p=n((()=>({messages:c,error:l||a,channel:d.current})),[c,l,a]);return i(D,{children:i(T.Provider,{value:p,children:r})})},B=()=>{const e=a(T);if(!e)throw new Error("useBroadcastProvider must be used within a BroadcastProvider");return e};export{A as BroadcastProvider,N as useBroadcastChannel,B as useBroadcastProvider};
2
2
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/utils/messageUtils.ts","../src/utils/debug.ts","../src/hooks/useBroadcastChannel.ts","../src/BroadcastProvider.tsx"],"sourcesContent":[null,null,null,null],"names":["INTERNAL_PREFIX","generateRandomPart","Math","random","toString","substr","generateMessageId","source","timestamp","raw","btoa","replace","isMessageExpired","message","expirationDate","Date","now","createMessage","type","content","options","id","_a","expirationDuration","undefined","getInternalMessageType","baseType","channelName","namespace","hash","isValidInternalClearMessage","startsWith","log","level","data","process","env","REACT_APP_DEBUG_BROADCAST","prefix","toISOString","console","warn","error","debug","created","name","closed","sent","received","cleared","messageId","expired","duplicate","allSentCleared","allReceivedCleared","ignored","messageType","inProgress","started","completed","removedCount","INTERNAL_MESSAGE_TYPES","flushSyncFn","NODE_ENV","require","flushSync","useBroadcastChannel","sourceName","cleaningInterval","keepLatestMessage","registeredTypes","deduplicationTTL","cleanupDebounceMs","messages","setMessages","useState","sentMessages","setSentMessages","setError","isPingInProgress","setIsPingInProgress","channel","useRef","receivedMessageIds","Map","activeSourcesCollector","useMemo","internalTypes","CLEAR_SENT_MESSAGES","PING","PONG","resolvedChannelName","stableRegisteredTypes","JSON","stringify","performCleanup","useCallback","prev","filter","msg","debouncedCleanup","debounce","fn","wait","result","timeoutId","lastArgs","debounced","args","clearTimeout","setTimeout","cancel","flush","Object","assign","current","setErrorMessage","ping","timeoutMs","Promise","resolve","collector","Set","postMessage","Array","from","messageContent","channelCurrent","e","clearReceivedMessages","hasFilters","Boolean","ids","length","types","sources","includes","clearSentMessages","sync","idMatches","typeMatches","_b","_c","getLatestMessage","i","sourceMatches","handleMessage","event","isValidMessage","pongSource","has","add","receivedAt","get","set","closeChannel","bc","close","removeEventListener","useEffect","BroadcastChannel","addEventListener","interval","setInterval","before","clearInterval","call","entries","delete","BroadcastChannelContext","createContext","ErrorBoundary","React","Component","constructor","this","state","hasError","getDerivedStateFromError","componentDidCatch","render","_jsx","props","children","BroadcastProvider","hookError","value","Provider","useBroadcastProvider","context","useContext","Error"],"mappings":"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"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/utils/messageUtils.ts","../src/utils/debug.ts","../src/hooks/useBroadcastChannel.ts","../src/BroadcastProvider.tsx"],"sourcesContent":[null,null,null,null],"names":["INTERNAL_PREFIX","generateRandomPart","Math","random","toString","substr","generateMessageId","source","timestamp","raw","btoa","replace","isMessageExpired","message","expirationDate","Date","now","createMessage","type","content","options","id","_a","expirationDuration","undefined","getInternalMessageType","baseType","channelName","namespace","hash","isValidInternalClearMessage","startsWith","log","level","data","process","env","REACT_APP_DEBUG_BROADCAST","prefix","toISOString","console","warn","error","debug","created","name","closed","sent","received","cleared","messageId","expired","duplicate","allSentCleared","allReceivedCleared","ignored","messageType","inProgress","started","completed","removedCount","INTERNAL_MESSAGE_TYPES","flushSyncFn","NODE_ENV","require","flushSync","useBroadcastChannel","sourceName","cleaningInterval","keepLatestMessage","registeredTypes","deduplicationTTL","cleanupDebounceMs","batchingDelayMs","excludedBatchMessageTypes","messages","setMessages","useState","sentMessages","setSentMessages","setError","isPingInProgress","setIsPingInProgress","channel","useRef","receivedMessageIds","Map","activeSourcesCollector","batchingTimeoutRef","batchingMessagesRef","batchingErrorRef","useMemo","internalTypes","CLEAR_SENT_MESSAGES","PING","PONG","resolvedChannelName","stableRegisteredTypes","JSON","stringify","performCleanup","useCallback","prev","filter","msg","debouncedCleanup","debounce","fn","wait","result","timeoutId","lastArgs","debounced","args","clearTimeout","setTimeout","cancel","flush","Object","assign","current","setErrorMessage","ping","timeoutMs","Promise","resolve","collector","Set","postMessage","Array","from","messageContent","channelCurrent","includes","e","push","clearReceivedMessages","hasFilters","Boolean","ids","length","types","sources","clearSentMessages","sync","idMatches","typeMatches","_b","_c","getLatestMessage","i","sourceMatches","handleMessage","event","isValidMessage","pongSource","has","add","receivedAt","get","set","closeChannel","bc","close","removeEventListener","useEffect","BroadcastChannel","addEventListener","isArray","forEach","interval","setInterval","before","clearInterval","call","key","entries","delete","BroadcastChannelContext","createContext","ErrorBoundary","React","Component","constructor","this","state","hasError","getDerivedStateFromError","componentDidCatch","render","_jsx","props","children","BroadcastProvider","hookError","value","Provider","useBroadcastProvider","context","useContext","Error"],"mappings":"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"}
@@ -16,6 +16,10 @@ export interface BroadcastOptions {
16
16
  deduplicationTTL?: number;
17
17
  /** Debounce time for messages cleanup in milliseconds (default: 1000) */
18
18
  cleanupDebounceMs?: number;
19
+ /** Delay in milliseconds for batching messages (default: 20) */
20
+ batchingDelayMs?: number;
21
+ /** Array of message types that should not be batched and sent immediately (default: []) */
22
+ excludedBatchMessageTypes?: string[];
19
23
  }
20
24
  /**
21
25
  * Options for sending messages
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-broadcast-sync",
3
- "version": "1.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "A lightweight React hook and provider for syncing state across browser tabs using BroadcastChannel API.",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.esm.js",
@@ -36,6 +36,16 @@ if (process.env.NODE_ENV === 'test') {
36
36
  }
37
37
  }
38
38
 
39
+ /**
40
+ * useBroadcastChannel hook
41
+ *
42
+ * Note: When batching is enabled (batchingDelayMs > 0), messages sent over the channel may be received as either:
43
+ * - a single BroadcastMessage (object), or
44
+ * - an array of BroadcastMessage (batch)
45
+ *
46
+ * The event handler in this hook supports both formats. If you listen to the channel directly, always check:
47
+ * if (Array.isArray(event.data)) { ... } else { ... }
48
+ */
39
49
  export const useBroadcastChannel = (
40
50
  channelName: string,
41
51
  options: BroadcastOptions = {}
@@ -48,6 +58,8 @@ export const useBroadcastChannel = (
48
58
  namespace = '',
49
59
  deduplicationTTL = 5 * 60 * 1000,
50
60
  cleanupDebounceMs = 0,
61
+ batchingDelayMs = 20,
62
+ excludedBatchMessageTypes = [],
51
63
  } = options;
52
64
 
53
65
  // State
@@ -60,6 +72,9 @@ export const useBroadcastChannel = (
60
72
  const channel = useRef<BroadcastChannel | null>(null);
61
73
  const receivedMessageIds = useRef(new Map<string, number>());
62
74
  const activeSourcesCollector = useRef<Set<string> | null>(null);
75
+ const batchingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
76
+ const batchingMessagesRef = useRef<BroadcastMessage[]>([]);
77
+ const batchingErrorRef = useRef(false);
63
78
 
64
79
  // Memoized values
65
80
  const source = useMemo(() => sourceName || generateSourceName(), [sourceName]);
@@ -77,7 +92,8 @@ export const useBroadcastChannel = (
77
92
  );
78
93
 
79
94
  const resolvedChannelName = useMemo(() => {
80
- return `${channelName}-${namespace}`;
95
+ // Only append dash if namespace is non-empty
96
+ return namespace ? `${channelName}-${namespace}` : channelName;
81
97
  }, [channelName, namespace]);
82
98
 
83
99
  const stableRegisteredTypes = useMemo(() => registeredTypes, [JSON.stringify(registeredTypes)]);
@@ -150,18 +166,45 @@ export const useBroadcastChannel = (
150
166
  return;
151
167
  }
152
168
 
153
- try {
154
- const message = createMessage(messageType, messageContent, source, options);
155
- channelCurrent.postMessage(message);
156
- debug.message.sent(message);
157
- setSentMessages(prev => [...prev, message]);
158
- } catch (e) {
159
- const error = 'Failed to send message';
160
- debug.error(error);
161
- setErrorMessage(error);
169
+ const message = createMessage(messageType, messageContent, source, options);
170
+ // Only batch if batchingDelayMs > 0 and messageType is not excluded
171
+ const shouldSendImmediately =
172
+ !batchingDelayMs || batchingDelayMs < 0 || excludedBatchMessageTypes.includes(messageType);
173
+ if (shouldSendImmediately) {
174
+ try {
175
+ channelCurrent.postMessage(message);
176
+ } catch (e) {
177
+ const error = 'Failed to send message';
178
+ debug.error(error);
179
+ setErrorMessage(error);
180
+ batchingErrorRef.current = true;
181
+ }
182
+ } else {
183
+ batchingMessagesRef.current.push(message);
184
+ if (!batchingTimeoutRef.current) {
185
+ batchingTimeoutRef.current = setTimeout(() => {
186
+ if (batchingErrorRef.current) {
187
+ batchingMessagesRef.current = [];
188
+ batchingTimeoutRef.current = null;
189
+ return;
190
+ }
191
+ try {
192
+ channelCurrent.postMessage(batchingMessagesRef.current);
193
+ } catch (e) {
194
+ const error = 'Failed to send message';
195
+ debug.error(error);
196
+ setErrorMessage(error);
197
+ batchingErrorRef.current = true;
198
+ }
199
+ batchingMessagesRef.current = [];
200
+ batchingTimeoutRef.current = null;
201
+ }, batchingDelayMs);
202
+ }
162
203
  }
204
+ debug.message.sent(message);
205
+ setSentMessages(prev => [...prev, message]);
163
206
  },
164
- [source, setErrorMessage]
207
+ [source, setErrorMessage, batchingDelayMs, excludedBatchMessageTypes]
165
208
  );
166
209
 
167
210
  const clearReceivedMessages = useCallback((options: ClearReceivedMessagesOptions = {}) => {
@@ -333,7 +376,16 @@ export const useBroadcastChannel = (
333
376
  channel.current = bc;
334
377
  debug.channel.created(resolvedChannelName);
335
378
 
336
- bc.addEventListener('message', handleMessage);
379
+ bc.addEventListener('message', (event: MessageEvent) => {
380
+ // event.data may be a single message or an array of messages (batch)
381
+ if (Array.isArray(event.data)) {
382
+ event.data.forEach((message: BroadcastMessage) => {
383
+ handleMessage({ data: message } as MessageEvent<BroadcastMessage>);
384
+ });
385
+ } else {
386
+ handleMessage(event);
387
+ }
388
+ });
337
389
  return () => {
338
390
  closeChannel();
339
391
  };
@@ -361,9 +413,9 @@ export const useBroadcastChannel = (
361
413
  useEffect(() => {
362
414
  const interval = setInterval(() => {
363
415
  const now = Date.now();
364
- for (const [id, timestamp] of receivedMessageIds.current.entries()) {
416
+ for (const [key, timestamp] of receivedMessageIds.current.entries()) {
365
417
  if (now - timestamp >= deduplicationTTL) {
366
- receivedMessageIds.current.delete(id);
418
+ receivedMessageIds.current.delete(key);
367
419
  }
368
420
  }
369
421
  }, 60 * 1000);
@@ -371,6 +423,29 @@ export const useBroadcastChannel = (
371
423
  return () => clearInterval(interval);
372
424
  }, [deduplicationTTL]);
373
425
 
426
+ useEffect(() => {
427
+ return () => {
428
+ // Always flush any unsent batched messages on unmount
429
+ if (batchingMessagesRef.current.length > 0 && channel.current && !batchingErrorRef.current) {
430
+ try {
431
+ channel.current.postMessage(batchingMessagesRef.current);
432
+ } catch (e) {
433
+ const error = 'Failed to send message';
434
+ debug.error(error);
435
+ setErrorMessage(error);
436
+ }
437
+ batchingMessagesRef.current = [];
438
+ // Allow event loop to process delivery for tests
439
+ setTimeout(() => {}, 0);
440
+ }
441
+ if (batchingTimeoutRef.current) {
442
+ clearTimeout(batchingTimeoutRef.current);
443
+ batchingTimeoutRef.current = null;
444
+ }
445
+ batchingErrorRef.current = false;
446
+ };
447
+ }, []);
448
+
374
449
  return {
375
450
  channelName: resolvedChannelName,
376
451
  messages,
@@ -65,7 +65,7 @@ describe('BroadcastProvider', () => {
65
65
 
66
66
  // The provider creates two channels - one in the provider and one in useBroadcastChannel
67
67
  expect(mockChannels).toHaveLength(2);
68
- expect(mockChannels[0].name).toBe('test-channel-');
68
+ expect(mockChannels[0].name).toBe('test-channel');
69
69
  expect(mockChannels[1].name).toBe('test-channel');
70
70
  });
71
71
 
@@ -16,7 +16,12 @@ class MockBroadcastChannel {
16
16
  if (channel.onmessage) {
17
17
  // Use setTimeout to simulate async behavior
18
18
  setTimeout(() => {
19
- channel.onmessage!({ data } as MessageEvent);
19
+ // Support both single and batched (array) messages
20
+ if (Array.isArray(data)) {
21
+ data.forEach(msg => channel.onmessage!({ data: msg } as MessageEvent));
22
+ } else {
23
+ channel.onmessage!({ data } as MessageEvent);
24
+ }
20
25
  }, 0);
21
26
  }
22
27
  });
@@ -37,7 +42,12 @@ class MockBroadcastChannel {
37
42
  simulateMessage(data: any) {
38
43
  if (this.onmessage) {
39
44
  setTimeout(() => {
40
- this.onmessage!({ data } as MessageEvent);
45
+ // Support both single and batched (array) messages
46
+ if (Array.isArray(data)) {
47
+ data.forEach(msg => this.onmessage!({ data: msg } as MessageEvent));
48
+ } else {
49
+ this.onmessage!({ data } as MessageEvent);
50
+ }
41
51
  }, 0);
42
52
  }
43
53
  }
@@ -74,6 +84,7 @@ describe('useBroadcastChannel - Same Tab Multi-Hook Behavior', () => {
74
84
  const testOptions = {
75
85
  cleaningInterval: 0, // Disable auto cleanup to avoid act warnings
76
86
  deduplicationTTL: 60000, // Long TTL for tests
87
+ batchingDelayMs: 0, // Disable batching for immediate delivery in tests
77
88
  };
78
89
 
79
90
  describe('1. Two Hooks with Different Source Names', () => {
@@ -204,8 +215,8 @@ describe('useBroadcastChannel - Same Tab Multi-Hook Behavior', () => {
204
215
  await waitForAsync();
205
216
 
206
217
  // Verify both hooks are working (channel name includes namespace suffix)
207
- expect(hook1.current.channelName).toBe(`${CHANNEL_NAME}-`);
208
- expect(hook2.current.channelName).toBe(`${CHANNEL_NAME}-`);
218
+ expect(hook1.current.channelName).toBe(`${CHANNEL_NAME}`);
219
+ expect(hook2.current.channelName).toBe(`${CHANNEL_NAME}`);
209
220
 
210
221
  // Unmount hook1
211
222
  unmount1();
@@ -24,7 +24,12 @@ class MockBroadcastChannel {
24
24
  const others = MockBroadcastChannel.channels[this.name] || [];
25
25
  for (const channel of others) {
26
26
  if (channel !== this && !channel.closed && channel._onmessage) {
27
- channel._onmessage({ data } as MessageEvent);
27
+ // Support both single and batched (array) messages
28
+ if (Array.isArray(data)) {
29
+ data.forEach(msg => channel._onmessage!({ data: msg } as MessageEvent));
30
+ } else {
31
+ channel._onmessage({ data } as MessageEvent);
32
+ }
28
33
  }
29
34
  }
30
35
  });
@@ -55,7 +60,12 @@ class MockBroadcastChannel {
55
60
 
56
61
  simulateMessage(data: any) {
57
62
  if (this.closed || !this._onmessage) return;
58
- this._onmessage({ data } as MessageEvent);
63
+ // Support both single and batched (array) messages
64
+ if (Array.isArray(data)) {
65
+ data.forEach(msg => this._onmessage!({ data: msg } as MessageEvent));
66
+ } else {
67
+ this._onmessage({ data } as MessageEvent);
68
+ }
59
69
  }
60
70
  }
61
71
 
@@ -331,7 +341,9 @@ describe('useBroadcastChannel', () => {
331
341
  });
332
342
 
333
343
  it('handles error when posting message fails', async () => {
334
- const { result } = renderHook(() => useBroadcastChannel('test-channel'));
344
+ const { result } = renderHook(() =>
345
+ useBroadcastChannel('test-channel', { batchingDelayMs: 0 })
346
+ );
335
347
  await waitForChannel();
336
348
  const channel = mockChannels[0];
337
349
 
@@ -1118,4 +1130,114 @@ describe('useBroadcastChannel', () => {
1118
1130
  expect(result.current.isPingInProgress).toBe(false);
1119
1131
  });
1120
1132
  });
1133
+
1134
+ describe('Batching', () => {
1135
+ it('batches multiple messages sent within the delay', async () => {
1136
+ jest.useFakeTimers();
1137
+ const { result: hook1 } = renderHook(() =>
1138
+ useBroadcastChannel('batch-channel', { batchingDelayMs: 50, sourceName: 'A' })
1139
+ );
1140
+ const { result: hook2 } = renderHook(() =>
1141
+ useBroadcastChannel('batch-channel', { sourceName: 'B' })
1142
+ );
1143
+ await waitForChannel();
1144
+ act(() => {
1145
+ hook1.current.postMessage('type1', { a: 1 });
1146
+ hook1.current.postMessage('type2', { b: 2 });
1147
+ });
1148
+ // Fast-forward batching delay
1149
+ act(() => {
1150
+ jest.advanceTimersByTime(51);
1151
+ });
1152
+ // Both messages should be received as a batch (array)
1153
+ await waitFor(() => {
1154
+ expect(hook2.current.messages.length).toBe(2);
1155
+ expect(hook2.current.messages[0].type).toBe('type1');
1156
+ expect(hook2.current.messages[1].type).toBe('type2');
1157
+ });
1158
+ jest.useRealTimers();
1159
+ });
1160
+
1161
+ it('excluded types are sent immediately', async () => {
1162
+ const { result: hook1 } = renderHook(() =>
1163
+ useBroadcastChannel('batch-channel', {
1164
+ batchingDelayMs: 50,
1165
+ excludedBatchMessageTypes: ['urgent'],
1166
+ sourceName: 'A',
1167
+ })
1168
+ );
1169
+ const { result: hook2 } = renderHook(() =>
1170
+ useBroadcastChannel('batch-channel', { sourceName: 'B' })
1171
+ );
1172
+ await waitForChannel();
1173
+ act(() => {
1174
+ hook1.current.postMessage('urgent', { now: true });
1175
+ });
1176
+ // Should be received immediately, not batched
1177
+ await waitFor(() => {
1178
+ expect(hook2.current.messages.length).toBe(1);
1179
+ expect(hook2.current.messages[0].type).toBe('urgent');
1180
+ });
1181
+ });
1182
+
1183
+ it('flushes unsent batched messages on unmount', async () => {
1184
+ const { result, unmount } = renderHook(() =>
1185
+ useBroadcastChannel('batch-channel', { batchingDelayMs: 0, sourceName: 'A' })
1186
+ );
1187
+ const { result: hook2 } = renderHook(() =>
1188
+ useBroadcastChannel('batch-channel', { sourceName: 'B' })
1189
+ );
1190
+ await waitForChannel();
1191
+ act(() => {
1192
+ result.current.postMessage('type1', { a: 1 });
1193
+ });
1194
+ // Unmount (should not affect immediate send)
1195
+ unmount();
1196
+ await waitFor(() => {
1197
+ expect(hook2.current.messages.length).toBe(1);
1198
+ expect(hook2.current.messages[0].type).toBe('type1');
1199
+ });
1200
+ });
1201
+
1202
+ it('handles both single and batch messages in the event handler', async () => {
1203
+ const { result } = renderHook(() =>
1204
+ useBroadcastChannel('batch-channel', { sourceName: 'A' })
1205
+ );
1206
+ await waitForChannel();
1207
+ const channel = mockChannels[0];
1208
+ // Simulate receiving a single message
1209
+ act(() => {
1210
+ channel.simulateMessage({
1211
+ id: '1',
1212
+ type: 'single',
1213
+ message: 'one',
1214
+ source: 'B',
1215
+ timestamp: Date.now(),
1216
+ });
1217
+ });
1218
+ // Simulate receiving a batch (array)
1219
+ act(() => {
1220
+ channel.simulateMessage([
1221
+ {
1222
+ id: '2',
1223
+ type: 'batch1',
1224
+ message: 'two',
1225
+ source: 'B',
1226
+ timestamp: Date.now(),
1227
+ },
1228
+ {
1229
+ id: '3',
1230
+ type: 'batch2',
1231
+ message: 'three',
1232
+ source: 'B',
1233
+ timestamp: Date.now(),
1234
+ },
1235
+ ]);
1236
+ });
1237
+ expect(result.current.messages.length).toBe(3);
1238
+ expect(result.current.messages[0].type).toBe('single');
1239
+ expect(result.current.messages[1].type).toBe('batch1');
1240
+ expect(result.current.messages[2].type).toBe('batch2');
1241
+ });
1242
+ });
1121
1243
  });
@@ -22,6 +22,12 @@ export interface BroadcastOptions {
22
22
 
23
23
  /** Debounce time for messages cleanup in milliseconds (default: 1000) */
24
24
  cleanupDebounceMs?: number;
25
+
26
+ /** Delay in milliseconds for batching messages (default: 20) */
27
+ batchingDelayMs?: number;
28
+
29
+ /** Array of message types that should not be batched and sent immediately (default: []) */
30
+ excludedBatchMessageTypes?: string[];
25
31
  }
26
32
 
27
33
  /**