UNPKG

laravel-echo

Version:

Laravel Echo library for beautiful Pusher, Socket.IO, and Mercure integration

2 lines • 31.3 kB
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});var e=class{constructor(){this.notificationCreatedEvent=`.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated`}listenForWhisper(e,t){return this.listen(`.client-`+e,t)}notification(e){return this.listen(this.notificationCreatedEvent,e)}stopListeningForNotification(e){return this.stopListening(this.notificationCreatedEvent,e)}stopListeningForWhisper(e,t){return this.stopListening(`.client-`+e,t)}},t=class{constructor(e){this.namespace=e}format(e){return[`.`,`\\`].includes(e.charAt(0))?e.substring(1):(this.namespace&&(e=this.namespace+`.`+e),e.replace(/\./g,`\\`))}setNamespace(e){this.namespace=e}};function n(e){try{return Reflect.construct(String,[],e),!0}catch{return!1}}var r=class extends e{constructor(e,n,r){super(),this.listeners=new Map,this.subscribedCallbacks=[],this.errorCallbacks=[],this.name=e,this.options=n,this.whisperer=r,this.eventFormatter=new t(this.options.namespace)}listen(e,t){let n=this.eventFormatter.format(e);return this.listeners.set(n,[...this.listeners.get(n)??[],t]),this}stopListening(e,t){let n=this.eventFormatter.format(e);if(!t)this.listeners.delete(n);else{let e=(this.listeners.get(n)??[]).filter(e=>e!==t);e.length===0?this.listeners.delete(n):this.listeners.set(n,e)}return this}subscribed(e){return this.subscribedCallbacks.push(e),this}error(e){return this.errorCallbacks.push(e),this}whisper(e,t){throw Error(`Public Mercure channels do not support whisper(): use a private or presence channel, whose members are granted a whisper topic.`)}listenForWhisper(e,t){return console.warn(`listenForWhisper("${e}"): public Mercure channels cannot receive whispers, so this listener will never fire.`),super.listenForWhisper(e,t)}dispatch(e,t){(this.listeners.get(e)??[]).forEach(e=>e(t))}notifySubscribed(){this.subscribedCallbacks.forEach(e=>e())}notifyError(e){this.errorCallbacks.forEach(t=>t(e))}},i=class extends r{whisper(e,t){if(!this.whisperer)throw Error(`whisper("${e}"): this channel was constructed without a connector to publish through.`);return this.whisperer.whisper(this.name,e,t),this}listenForWhisper(e,t){return this.whisperer?.listenForWhispers(this.name),this.listen(`.client-`+e,t)}},a=class extends i{},o=class extends i{constructor(...e){super(...e),this.hereCallbacks=[],this.joiningCallbacks=[],this.leavingCallbacks=[],this.members=new Map,this.memberCounts=new Map,this.seeded=!1}here(e){return this.hereCallbacks.push(e),this.seeded&&this.invoke(e,this.uniqueMembers()),this}joining(e){return this.joiningCallbacks.push(e),this}leaving(e){return this.leavingCallbacks.push(e),this}setInitialMembers(e){this.members=new Map(e.map(([e,t])=>[e,s(t)])),this.memberCounts=new Map;for(let e of this.members.values())this.memberCounts.set(e.key,(this.memberCounts.get(e.key)??0)+1);this.seeded=!0,this.hereCallbacks.forEach(e=>this.invoke(e,this.uniqueMembers()))}applySubscriptionEvent(e,t,n){if(t){if(this.members.has(e))return;let t=s(n??{}),r=(this.memberCounts.get(t.key)??0)+1;this.members.set(e,t),this.memberCounts.set(t.key,r),r===1&&this.joiningCallbacks.forEach(e=>this.invoke(e,t.info))}else{let t=this.members.get(e);if(!t)return;let n=(this.memberCounts.get(t.key)??1)-1;this.members.delete(e),n<=0?(this.memberCounts.delete(t.key),this.leavingCallbacks.forEach(e=>this.invoke(e,t.info))):this.memberCounts.set(t.key,n)}}uniqueMembers(){let e=new Set,t=[];for(let n of this.members.values())e.has(n.key)||(e.add(n.key),t.push(n.info));return t}invoke(e,t){try{e(t)}catch(e){console.error(`A "${this.name}" presence callback threw:`,e)}}};function s(e){if(typeof e==`object`&&e&&`user_id`in e&&typeof e.user_id==`string`){let t=e;return{key:`user:`+t.user_id,info:t.user_info}}return{key:`payload:`+(JSON.stringify(e)??`undefined`),info:e}}var c=class extends e{constructor(e,n,r){super(),this.name=n,this.pusher=e,this.options=r,this.eventFormatter=new t(this.options.namespace),this.subscribe()}subscribe(){this.subscription=this.pusher.subscribe(this.name)}unsubscribe(){this.pusher.unsubscribe(this.name)}listen(e,t){return this.on(this.eventFormatter.format(e),t),this}listenToAll(e){return this.subscription.bind_global((t,n)=>{if(t.startsWith(`pusher:`))return;let r=String(this.options.namespace??``).replace(/\./g,`\\`);e(t.startsWith(r)?t.substring(r.length+1):`.`+t,n)}),this}stopListening(e,t){return t?this.subscription.unbind(this.eventFormatter.format(e),t):this.subscription.unbind(this.eventFormatter.format(e)),this}stopListeningToAll(e){return e?this.subscription.unbind_global(e):this.subscription.unbind_global(),this}subscribed(e){return this.on(`pusher:subscription_succeeded`,()=>{e()}),this}error(e){return this.on(`pusher:subscription_error`,t=>{e(t)}),this}on(e,t){return this.subscription.bind(e,t),this}},l=class extends c{whisper(e,t){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,t),this}},u=class extends c{whisper(e,t){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,t),this}},d=class extends l{here(e){return this.on(`pusher:subscription_succeeded`,t=>{e(Object.keys(t.members).map(e=>t.members[e]))}),this}joining(e){return this.on(`pusher:member_added`,t=>{e(t.info)}),this}whisper(e,t){return this.pusher.channels.channels[this.name].trigger(`client-${e}`,t),this}leaving(e){return this.on(`pusher:member_removed`,t=>{e(t.info)}),this}},f=class extends e{constructor(e,n,r){super(),this.events={},this.listeners={},this.name=n,this.socket=e,this.options=r,this.eventFormatter=new t(this.options.namespace),this.subscribe()}subscribe(){this.socket.emit(`subscribe`,{channel:this.name,auth:this.options.auth||{}})}unsubscribe(){this.unbind(),this.socket.emit(`unsubscribe`,{channel:this.name,auth:this.options.auth||{}})}listen(e,t){return this.on(this.eventFormatter.format(e),t),this}stopListening(e,t){return this.unbindEvent(this.eventFormatter.format(e),t),this}subscribed(e){return this.on(`connect`,t=>{e(t)}),this}error(e){return this}on(e,t){return this.listeners[e]=this.listeners[e]||[],this.events[e]||(this.events[e]=(t,n)=>{this.name===t&&this.listeners[e]&&this.listeners[e].forEach(e=>e(n))},this.socket.on(e,this.events[e])),this.listeners[e].push(t),this}unbind(){Object.keys(this.events).forEach(e=>{this.unbindEvent(e)})}unbindEvent(e,t){this.listeners[e]=this.listeners[e]||[],t&&(this.listeners[e]=this.listeners[e].filter(e=>e!==t)),t&&this.listeners[e].length!==0||(this.events[e]&&(this.socket.removeListener(e,this.events[e]),delete this.events[e]),delete this.listeners[e])}},p=class extends f{whisper(e,t){return this.socket.emit(`client event`,{channel:this.name,event:`client-${e}`,data:t}),this}},m=class extends p{here(e){return this.on(`presence:subscribed`,t=>{e(t.map(e=>e.user_info))}),this}joining(e){return this.on(`presence:joining`,t=>e(t.user_info)),this}whisper(e,t){return this.socket.emit(`client event`,{channel:this.name,event:`client-${e}`,data:t}),this}leaving(e){return this.on(`presence:leaving`,t=>e(t.user_info)),this}},h=class extends e{subscribe(){}unsubscribe(){}listen(e,t){return this}listenToAll(e){return this}stopListening(e,t){return this}subscribed(e){return this}error(e){return this}on(e,t){return this}},g=class extends h{whisper(e,t){return this}},_=class extends h{whisper(e,t){return this}},v=class extends g{here(e){return this}joining(e){return this}whisper(e,t){return this}leaving(e){return this}},y=class e{static{this._defaultOptions={auth:{headers:{}},authEndpoint:`/broadcasting/auth`,userAuthentication:{endpoint:`/broadcasting/user-auth`,headers:{}},csrfToken:null,bearerToken:null,host:null,key:null,namespace:`App.Events`}}constructor(e){this.setOptions(e),this.connect()}setOptions(t){this.options={...e._defaultOptions,...t,broadcaster:t.broadcaster};let n=this.csrfToken();n&&(this.options.auth.headers[`X-CSRF-TOKEN`]=n,this.options.userAuthentication.headers[`X-CSRF-TOKEN`]=n),n=this.options.bearerToken,n&&(this.options.auth.headers.Authorization=`Bearer `+n,this.options.userAuthentication.headers.Authorization=`Bearer `+n)}csrfToken(){return typeof window<`u`&&window.Laravel?.csrfToken?window.Laravel.csrfToken:this.options.csrfToken?this.options.csrfToken:typeof document<`u`&&typeof document.querySelector==`function`?document.querySelector(`meta[name="csrf-token"]`)?.getAttribute(`content`)??null:null}},b=`/.well-known/mercure`,x=3e4,S=100,C=`mercure`,w=`private-encrypted-`,T=`client-`,E=class extends y{constructor(...e){super(...e),this.channels=Object.create(null),this.eventSource=null,this.lastEventId=``,this.whisperEventSources=new Map,this.whisperLastEventIds=new Map,this.whisperListening=new Set,this.clientEventsEnabled=!1,this.topicPrefix=``,this.whisperQueue=Promise.resolve(),this.id=I(),this.status=`disconnected`,this.statusListeners=[],this.refreshing=!1,this.refreshPending=!1,this.authorizedChannels=new Set,this.subscribedNotified=new Set,this.seededPresenceChannels=new Set,this.pendingSubscriptionEvents=new Map,this.channelJwks=new Map,this.importedKeys=new Map,this.dispatchQueue=Promise.resolve(),this.epoch=0,this.reconnectDelay=1e3,this.reconnectTimer=null,this.tokenTtl=null,this.lastAuthAt=0,this.tokenRefreshTimer=null}connect(){let e=typeof window<`u`;if(this.options.host==null&&!e)throw Error(`Mercure connector: the "host" option (the hub URL) is required outside a browser.`);try{this.url=new URL(this.options.host??b,e?window.location.origin:void 0)}catch{throw Error(`Mercure connector: the "host" option ("${String(this.options.host)}") is not a valid hub URL.`)}}eventSourceClass(){let e=this.options.eventSource??globalThis.EventSource;if(e===void 0)throw Error(`Mercure connector: EventSource is not available globally; pass an implementation via the "eventSource" option.`);return e}subscriptionsPath(){return`${this.url.pathname.replace(/\/$/,``)}/subscriptions`}channelTopic(e){return this.topicPrefix===``?e:`${this.topicPrefix}channel/${F(e)}`}whisperTopic(e){return`${this.topicPrefix}whisper/${F(e)}`}channelNameFromTopic(e){if(this.topicPrefix===``)return e;let t=`${this.topicPrefix}channel/`;if(!e.startsWith(t))return null;try{return decodeURIComponent(e.slice(t.length))}catch{return null}}listen(e,t,n){return this.channel(e).listen(t,n)}channel(e){return this.channels[e]||(this.channels[e]=new r(e,this.options,this),this.refresh()),this.channels[e]}privateChannel(e){let t=`private-`+e;return this.channels[t]||(this.channels[t]=new i(t,this.options,this),this.refresh()),this.channels[t]}encryptedPrivateChannel(e){let t=w+e;return this.channels[t]||(this.channels[t]=new a(t,this.options,this),this.refresh()),this.channels[t]}presenceChannel(e){let t=`presence-`+e;return this.channels[t]||(this.channels[t]=new o(t,this.options,this),this.refresh()),this.channels[t]}leave(e){[``,`private-`,w,`presence-`].forEach(t=>this.leaveChannel(t+e))}leaveChannel(e){this.channels[e]&&(delete this.channels[e],this.forgetChannelState(e),this.refresh())}socketId(){return this.id}whisper(e,t,n){let r=this.channels[e];r&&(this.clientEventsEnabled?this.whisperQueue=this.whisperQueue.then(()=>this.publishWhisper(e,T+t,n).catch(t=>{this.channels[e]?.notifyError(t)})):r.notifyError(Error(`whisper("${t}"): the server did not grant client events; enable the "client_events" option of the Mercure broadcasting connection.`)))}listenForWhispers(e){!this.whisperListening.has(e)&&this.channels[e]&&(this.whisperListening.add(e),this.syncWhisperEventSources())}async publishWhisper(e,t,n){let r;r=e.startsWith(w)?JSON.stringify({channels:[e],data:await this.encrypt(e,JSON.stringify({event:t,payload:n,socket:this.id}))}):JSON.stringify({channels:[e],event:t,payload:n,socket:this.id});let i=()=>fetch(`${this.url.origin}${this.url.pathname}`,{method:`POST`,credentials:`include`,body:new URLSearchParams({topic:this.whisperTopic(e),data:r,private:`on`})}),a=await i();if(a.status===401&&this.channels[e]){let t=await this.authenticate(Object.keys(this.channels));t.ok&&(t.denied.length>0&&(this.evict(t.denied,Error(`The broadcasting auth request denied access to [${t.denied.join(`, `)}].`)),this.refresh()),this.channels[e]&&(a=await i()))}if(!a.ok)throw Error(`The whisper publish on "${e}" failed with HTTP ${a.status}.`)}connectionStatus(){return this.status}onConnectionChange(e){return this.statusListeners.push(e),()=>{this.statusListeners=this.statusListeners.filter(t=>t!==e)}}disconnect(){this.epoch++,this.channels=Object.create(null),this.authorizedChannels.clear(),this.subscribedNotified.clear(),this.seededPresenceChannels.clear(),this.pendingSubscriptionEvents.clear(),this.channelJwks.clear(),this.importedKeys.clear(),this.lastEventId=``,this.whisperLastEventIds.clear(),this.whisperListening.clear(),this.clientEventsEnabled=!1,this.topicPrefix=``,this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null),this.reconnectDelay=1e3,this.tokenRefreshTimer&&=(clearTimeout(this.tokenRefreshTimer),null),this.eventSource?.close(),this.eventSource=null,this.closeWhisperEventSources(),this.setStatus(`disconnected`)}setStatus(e){this.status=e,this.statusListeners.forEach(t=>t(e))}forgetChannelState(e){this.authorizedChannels.delete(e),this.subscribedNotified.delete(e),this.seededPresenceChannels.delete(e),this.pendingSubscriptionEvents.delete(e),this.channelJwks.delete(e),this.importedKeys.delete(e),this.whisperEventSources.get(e)?.close(),this.whisperEventSources.delete(e),this.whisperLastEventIds.delete(e),this.whisperListening.delete(e)}evict(e,t){e.forEach(e=>{let n=this.channels[e];n&&(delete this.channels[e],this.forgetChannelState(e),n.notifyError(t))})}notifyAllError(e){Object.values(this.channels).forEach(t=>t.notifyError(e))}guardedChannelNames(){return Object.keys(this.channels).filter(e=>e.startsWith(`private-`)||e.startsWith(`presence-`))}refresh(){this.runExclusive(()=>this.doRefresh())}runExclusive(e){this.refreshing?this.refreshPending=!0:(this.refreshing=!0,e().catch(e=>{this.notifyAllError(e),Object.keys(this.channels).length>0&&(this.setStatus(`reconnecting`),this.scheduleReconnect())}).finally(()=>{this.refreshing=!1,this.refreshPending&&(this.refreshPending=!1,this.refresh())}))}scheduleTokenRefresh(){if(this.tokenTtl===null)return;this.tokenRefreshTimer&&clearTimeout(this.tokenRefreshTimer);let e=this.epoch;this.tokenRefreshTimer=setTimeout(()=>{this.tokenRefreshTimer=null,e===this.epoch&&Object.keys(this.channels).length!==0&&(this.tokenTtl!==null&&Date.now()-this.lastAuthAt>=this.tokenTtl*1e3?this.refresh():this.runExclusive(async()=>{let t=await this.authenticate(Object.keys(this.channels));e===this.epoch&&(t.ok?(t.denied.length>0&&(this.evict(t.denied,Error(`The broadcasting auth request denied access to [${t.denied.join(`, `)}].`)),this.refresh()),this.scheduleTokenRefresh()):(this.notifyAllError(t.error),this.scheduleReconnect()))}))},Math.max(this.tokenTtl*.8*1e3,5e3))}scheduleReconnect(){if(this.reconnectTimer)return;let e=this.epoch;this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,e===this.epoch&&Object.keys(this.channels).length!==0&&this.refresh()},this.reconnectDelay),this.reconnectDelay=Math.min(this.reconnectDelay*2,x)}async doRefresh(){let e=this.epoch;if(await Promise.resolve(),e!==this.epoch)return;this.refreshPending=!1;let t=Object.keys(this.channels);if(t.length===0){this.eventSource?.close(),this.eventSource=null,this.closeWhisperEventSources(),this.authorizedChannels.clear(),this.setStatus(`disconnected`);return}t.length>S&&(this.evict(t.slice(S),Error(`Mercure broadcasting authorizes at most ${S} channels per connection.`)),t=t.slice(0,S)),this.eventSource||this.setStatus(`connecting`);let n=await this.authenticate(t);if(e!==this.epoch)return;if(!n.ok){let e=t.filter(e=>!this.authorizedChannels.has(e)&&this.channels[e]);if(n.rejected&&e.length>0){this.evict(e,Error(`The broadcasting auth request was denied (HTTP ${String(n.status)}) after joining [${e.join(`, `)}].`)),this.refreshPending=!0;return}this.notifyAllError(n.error),this.setStatus(`reconnecting`),this.scheduleReconnect();return}if(this.reconnectTimer&&=(clearTimeout(this.reconnectTimer),null),n.denied.length>0&&(this.evict(n.denied,Error(`The broadcasting auth request denied access to [${n.denied.join(`, `)}].`)),t=t.filter(e=>this.channels[e]),t.length===0)){this.eventSource?.close(),this.eventSource=null,this.closeWhisperEventSources(),this.authorizedChannels.clear(),this.setStatus(`disconnected`);return}this.authorizedChannels=new Set(t),this.scheduleTokenRefresh(),t.filter(e=>this.channels[e]instanceof o&&!this.seededPresenceChannels.has(e)&&!this.pendingSubscriptionEvents.has(e)).forEach(e=>this.pendingSubscriptionEvents.set(e,[]));let r=this.buildSubscribeUrl(t.map(e=>this.channelTopic(e)),t.filter(e=>this.channels[e]instanceof o).map(e=>this.subscriptionEventsPattern(e)),this.lastEventId),i=this.eventSourceClass();this.eventSource?.close();let a=new i(r.toString(),{withCredentials:!0});this.eventSource=a,a.onopen=()=>{this.eventSource===a&&(this.reconnectDelay=1e3,this.setStatus(`connected`),t.forEach(e=>{let t=this.channels[e];t&&!this.subscribedNotified.has(e)&&(this.subscribedNotified.add(e),t.notifySubscribed())}),this.seedPresenceChannels(e))},a.onerror=e=>{this.eventSource===a&&(this.notifyAllError(e),this.setStatus(`reconnecting`),a.readyState===i.CLOSED&&(this.subscribedNotified.clear(),this.seededPresenceChannels.clear(),this.pendingSubscriptionEvents.clear(),this.scheduleReconnect()))},a.onmessage=e=>{this.eventSource===a&&this.handleMessage(e)},a.addEventListener(C,e=>{this.eventSource===a&&this.handleSubscriptionEvent(e)}),this.syncWhisperEventSources()}buildSubscribeUrl(e,t,n){let r=new URL(this.url);return r.search=``,e.forEach(e=>r.searchParams.append(`match`,e)),t.forEach(e=>r.searchParams.append(`match_urlpattern`,e)),n&&r.searchParams.set(`last_event_id`,n),r}closeWhisperEventSources(){this.whisperEventSources.forEach(e=>e.close()),this.whisperEventSources.clear()}syncWhisperEventSources(){let e=this.eventSourceClass().CLOSED,t=new Set(this.clientEventsEnabled?this.guardedChannelNames().filter(e=>this.authorizedChannels.has(e)&&this.whisperListening.has(e)):[]);this.whisperEventSources.forEach((n,r)=>{t.has(r)&&n.readyState!==e||(n.close(),this.whisperEventSources.delete(r))}),this.clientEventsEnabled?t.forEach(e=>{this.whisperEventSources.has(e)||this.openWhisperEventSource(e)}):this.whisperLastEventIds.clear()}openWhisperEventSource(e){let t=this.eventSourceClass(),n=new t(this.buildSubscribeUrl([this.whisperTopic(e)],[],this.whisperLastEventIds.get(e)??``).toString(),{withCredentials:!0});this.whisperEventSources.set(e,n),n.onmessage=t=>{this.whisperEventSources.get(e)===n&&(this.whisperLastEventIds.set(e,t.lastEventId),this.handleWhisperMessage(t,e))},n.onerror=()=>{this.whisperEventSources.get(e)===n&&n.readyState===t.CLOSED&&this.scheduleReconnect()}}async seedPresenceChannels(e){await Promise.all([...this.pendingSubscriptionEvents.keys()].map(async t=>{let n=this.channels[t];if(!(n instanceof o))this.pendingSubscriptionEvents.delete(t);else try{let r=await this.fetchPresenceSnapshot(t);if(e!==this.epoch)return;this.seededPresenceChannels.add(t),n.setInitialMembers(r),(this.pendingSubscriptionEvents.get(t)??[]).forEach(([e,t,r])=>n.applySubscriptionEvent(e,t,r))}catch(e){n.notifyError(e)}finally{this.pendingSubscriptionEvents.delete(t)}}))}handleMessage(e){this.lastEventId=e.lastEventId;let t=O(e.data);if(!t||!Array.isArray(t.channels))return;let n=t.channels.filter(e=>typeof e==`string`);if(typeof t.data==`string`){let e=t.data;n.filter(e=>e.startsWith(w)&&D(this.channels,e)).forEach(t=>{this.dispatchQueue=this.dispatchQueue.then(()=>this.dispatchEncrypted(t,e))})}else t.socket&&t.socket===this.id||typeof t.event==`string`&&n.forEach(e=>{!e.startsWith(w)&&D(this.channels,e)&&this.channels[e].dispatch(t.event,t.payload)})}handleWhisperMessage(e,t){let n=O(e.data);if(n&&Array.isArray(n.channels)&&n.channels.length===1&&n.channels[0]===t&&D(this.channels,t)){if(typeof n.data==`string`){let e=n.data;t.startsWith(w)&&(this.dispatchQueue=this.dispatchQueue.then(()=>this.dispatchEncrypted(t,e,!0)))}else n.socket&&n.socket===this.id||typeof n.event==`string`&&n.event.startsWith(T)&&!t.startsWith(w)&&this.channels[t].dispatch(n.event,n.payload)}}async dispatchEncrypted(e,t,n=!1){let r=this.channels[e];if(r)try{let i=O(await this.decrypt(e,t));if(!i||typeof i.event!=`string`)throw Error(`The decrypted update on "${e}" carries no broadcast envelope.`);if(n&&!i.event.startsWith(T)||i.socket&&i.socket===this.id)return;r.dispatch(i.event,i.payload)}catch(e){r.notifyError(e)}}async decrypt(e,t){let n=t.split(`.`);if(n.length!==5||n[1]!==``)throw Error(`The update on "${e}" is not a direct-encryption compact JWE.`);let[r,,i,a,o]=n,s=O(j.decode(N(r)));if(s?.alg!==`dir`||s?.enc!==`A256GCM`)throw Error(`The update on "${e}" uses an unsupported JWE algorithm.`);let c=N(a),l=N(o),u=new Uint8Array(c.length+l.length);u.set(c),u.set(l,c.length);let d=await crypto.subtle.decrypt({name:`AES-GCM`,iv:N(i),additionalData:A.encode(r),tagLength:128},await this.channelKey(e),u);return j.decode(d)}async encrypt(e,t){let n=M,r=crypto.getRandomValues(new Uint8Array(12)),i=new Uint8Array(await crypto.subtle.encrypt({name:`AES-GCM`,iv:r,additionalData:A.encode(n),tagLength:128},await this.channelKey(e),A.encode(t))),a=i.slice(0,-16),o=i.slice(-16);return[n,``,P(r),P(a),P(o)].join(`.`)}channelKey(e){let t=this.channelJwks.get(e);if(!t||typeof t.k!=`string`)return Promise.reject(Error(`No decryption key is known for "${e}": the auth endpoint returned none. Is "encryption_key" configured server-side?`));let n=this.importedKeys.get(e);if(n&&n.k===t.k)return n.key;let r=crypto.subtle.importKey(`jwk`,t,{name:`AES-GCM`},!1,[`encrypt`,`decrypt`]);return this.importedKeys.set(e,{k:t.k,key:r}),r}handleSubscriptionEvent(e){this.lastEventId=e.lastEventId;let t=O(e.data);if(!t||typeof t.match!=`string`||typeof t.subscriber!=`string`||typeof t.active!=`boolean`||t.match_type!==`exact`||t.active&&t.payload==null)return;let n=this.channelNameFromTopic(t.match);if(n===null)return;let r=this.pendingSubscriptionEvents.get(n);if(r){r.push([t.subscriber,t.active,t.payload]);return}if(!D(this.channels,n))return;let i=this.channels[n];i instanceof o&&i.applySubscriptionEvent(t.subscriber,t.active,t.payload)}async fetchPresenceSnapshot(e){let t=await fetch(`${this.url.origin}${this.subscriptionsPath()}/exact/${F(this.channelTopic(e))}`,{credentials:`include`});if(!t.ok)throw Error(`The subscription snapshot request failed with HTTP ${t.status}.`);return((await t.json()).subscriptions??[]).filter(e=>e.active&&e.payload!=null).map(e=>[e.subscriber,e.payload])}async authenticate(e){let t,n=null;try{let r=await fetch(this.options.authEndpoint,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`,Accept:`application/json`,...this.options.auth.headers},body:JSON.stringify({channel_names:e})});if(r.ok)return this.lastAuthAt=Date.now(),{ok:!0,rejected:!1,status:r.status,denied:this.readAuthResponse(await k(r))};n=r.status,t=Error(`The broadcasting auth request to "${this.options.authEndpoint}" failed with HTTP ${r.status}.`)}catch(e){t=Error(`The broadcasting auth request to "${this.options.authEndpoint}" failed: ${e instanceof Error?e.message:String(e)}.`)}return{ok:!1,rejected:n!==null&&n<500,status:n,denied:[],error:t}}readAuthResponse(e){let t=e??{},n=Number(t.expires_in);this.tokenTtl=Number.isFinite(n)&&n>0?n:null,this.topicPrefix=typeof t.topic_prefix==`string`?t.topic_prefix:``,this.clientEventsEnabled=t.client_events===!0,this.channelJwks.clear();let r=[];return Array.isArray(t.channel_names)&&t.channel_names.forEach(e=>{let t=e??{};typeof t.name==`string`&&(t.denied===!0?r.push(t.name):t.jwk!==null&&typeof t.jwk==`object`&&this.channelJwks.set(t.name,t.jwk))}),r}subscriptionEventsPattern(e){return`${this.subscriptionsPath()}/:match_type/${F(this.channelTopic(e))}/:subscriber`}};function D(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function O(e){try{return JSON.parse(e)}catch{return null}}async function k(e){try{return await e.json()}catch{return null}}var A=new TextEncoder,j=new TextDecoder,M=P(A.encode(JSON.stringify({alg:`dir`,enc:`A256GCM`})));function N(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`)+`=`.repeat((4-e.length%4)%4);return Uint8Array.from(atob(t),e=>e.charCodeAt(0))}function P(e){return btoa(String.fromCharCode(...e)).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function F(e){return encodeURIComponent(e).replace(/[!'()*]/g,e=>`%`+e.charCodeAt(0).toString(16).toUpperCase())}function I(){return typeof crypto<`u`&&typeof crypto.randomUUID==`function`?crypto.randomUUID():Math.random().toString(36).slice(2)+Date.now().toString(36)}var L=class extends y{constructor(...e){super(...e),this.channels={}}connect(){if(this.options.client!==void 0)this.pusher=this.options.client;else if(this.options.Pusher)this.pusher=new this.options.Pusher(this.options.key,this.options);else if(typeof window<`u`&&window.Pusher!==void 0)this.pusher=new window.Pusher(this.options.key,this.options);else throw Error(`Pusher client not found. Should be globally available or passed via options.client`)}signin(){this.pusher.signin()}listen(e,t,n){return this.channel(e).listen(t,n)}channel(e){return this.channels[e]||(this.channels[e]=new c(this.pusher,e,this.options)),this.channels[e]}privateChannel(e){return this.channels[`private-`+e]||(this.channels[`private-`+e]=new l(this.pusher,`private-`+e,this.options)),this.channels[`private-`+e]}encryptedPrivateChannel(e){return this.channels[`private-encrypted-`+e]||(this.channels[`private-encrypted-`+e]=new u(this.pusher,`private-encrypted-`+e,this.options)),this.channels[`private-encrypted-`+e]}presenceChannel(e){return this.channels[`presence-`+e]||(this.channels[`presence-`+e]=new d(this.pusher,`presence-`+e,this.options)),this.channels[`presence-`+e]}leave(e){[e,`private-`+e,`private-encrypted-`+e,`presence-`+e].forEach(e=>{this.leaveChannel(e)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.pusher.connection.socket_id}connectionStatus(){let e=this.pusher.connection.state;switch(e){case`connected`:case`connecting`:return e;case`failed`:case`unavailable`:return`failed`;default:return`disconnected`}}onConnectionChange(e){let t=()=>{e(this.connectionStatus())},n=[`state_change`,`connected`,`disconnected`];return n.forEach(e=>{this.pusher.connection.bind(e,t)}),()=>{n.forEach(e=>{this.pusher.connection.unbind(e,t)})}}disconnect(){this.pusher.disconnect()}},R=class extends y{constructor(...e){super(...e),this.channels={}}connect(){let e=this.getSocketIO();this.socket=e(this.options.host??void 0,this.options),this.socket.io.on(`reconnect`,()=>{Object.values(this.channels).forEach(e=>{e.subscribe()})})}getSocketIO(){if(this.options.client!==void 0)return this.options.client;if(typeof window<`u`&&window.io!==void 0)return window.io;throw Error(`Socket.io client not found. Should be globally available or passed via options.client`)}listen(e,t,n){return this.channel(e).listen(t,n)}channel(e){return this.channels[e]||(this.channels[e]=new f(this.socket,e,this.options)),this.channels[e]}privateChannel(e){return this.channels[`private-`+e]||(this.channels[`private-`+e]=new p(this.socket,`private-`+e,this.options)),this.channels[`private-`+e]}presenceChannel(e){return this.channels[`presence-`+e]||(this.channels[`presence-`+e]=new m(this.socket,`presence-`+e,this.options)),this.channels[`presence-`+e]}leave(e){[e,`private-`+e,`presence-`+e].forEach(e=>{this.leaveChannel(e)})}leaveChannel(e){this.channels[e]&&(this.channels[e].unsubscribe(),delete this.channels[e])}socketId(){return this.socket.id}connectionStatus(){return this.socket.connected?`connected`:this.socket.io._reconnecting?`reconnecting`:this.socket.id===void 0?`connecting`:`disconnected`}onConnectionChange(e){let t=()=>{e(this.connectionStatus())},n=[`connect`,`disconnect`,`connect_error`,`reconnect_attempt`,`reconnect`,`reconnect_error`,`reconnect_failed`];return n.forEach(e=>{this.socket.on(e,t)}),()=>{n.forEach(e=>{this.socket.off(e,t)})}}disconnect(){this.socket.disconnect()}},z=class extends y{constructor(...e){super(...e),this.channels={}}connect(){}listen(e,t,n){return new h}channel(e){return new h}privateChannel(e){return new g}encryptedPrivateChannel(e){return new _}presenceChannel(e){return new v}leave(e){}leaveChannel(e){}socketId(){return`fake-socket-id`}connectionStatus(){return`connected`}onConnectionChange(e){return()=>{}}disconnect(){}},B=class{constructor(e){this.options=e,this.connect(),this.options.withoutInterceptors||this.registerInterceptors()}channel(e){return this.connector.channel(e)}connect(){if(this.options.broadcaster===`reverb`)this.connector=new L({...this.options,cluster:``});else if(this.options.broadcaster===`pusher`)this.connector=new L(this.options);else if(this.options.broadcaster===`ably`)this.connector=new L({...this.options,cluster:``,broadcaster:`pusher`});else if(this.options.broadcaster===`socket.io`)this.connector=new R(this.options);else if(this.options.broadcaster===`mercure`)this.connector=new E(this.options);else if(this.options.broadcaster===`null`)this.connector=new z(this.options);else if(typeof this.options.broadcaster==`function`&&n(this.options.broadcaster))this.connector=new this.options.broadcaster(this.options);else throw Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} is not supported.`)}disconnect(){this.connector.disconnect()}join(e){return this.connector.presenceChannel(e)}leave(e){this.connector.leave(e)}leaveChannel(e){this.connector.leaveChannel(e)}leaveAllChannels(){for(let e in this.connector.channels)this.leaveChannel(e)}listen(e,t,n){return this.connector.listen(e,t,n)}private(e){return this.connector.privateChannel(e)}encryptedPrivate(e){if(this.connectorSupportsEncryptedPrivateChannels(this.connector))return this.connector.encryptedPrivateChannel(e);throw Error(`Broadcaster ${typeof this.options.broadcaster} ${String(this.options.broadcaster)} does not support encrypted private channels.`)}connectorSupportsEncryptedPrivateChannels(e){return e instanceof L||e instanceof E||e instanceof z}socketId(){return this.connector.socketId()}connectionStatus(){return this.connector.connectionStatus()}registerInterceptors(){typeof Vue<`u`&&Vue?.http&&this.registerVueRequestInterceptor(),typeof axios==`function`&&this.registerAxiosRequestInterceptor(),typeof jQuery==`function`&&this.registerjQueryAjaxSetup(),typeof Turbo==`object`&&this.registerTurboRequestInterceptor()}registerVueRequestInterceptor(){Vue.http.interceptors.push((e,t)=>{this.socketId()&&e.headers.set(`X-Socket-ID`,this.socketId()),t()})}registerAxiosRequestInterceptor(){axios.interceptors.request.use(e=>(this.socketId()&&(e.headers[`X-Socket-Id`]=this.socketId()),e))}registerjQueryAjaxSetup(){jQuery.ajax!==void 0&&jQuery.ajaxPrefilter((e,t,n)=>{this.socketId()&&n.setRequestHeader(`X-Socket-Id`,this.socketId())})}registerTurboRequestInterceptor(){document.addEventListener(`turbo:before-fetch-request`,e=>{e.detail.fetchOptions.headers[`X-Socket-Id`]=this.socketId()})}};exports.Channel=e,exports.Connector=y,exports.EventFormatter=t,exports.default=B; //# sourceMappingURL=echo.common.js.map