UNPKG

pubnub

Version:

Publish & Subscribe Real-time Messaging with PubNub

3 lines (2 loc) 28.5 kB
!function(e){"function"==typeof define&&define.amd?define(e):e()}((function(){"use strict";function e(e,t,n,r){return new(n||(n=Promise))((function(s,i){function o(e){try{c(r.next(e))}catch(e){i(e)}}function a(e){try{c(r.throw(e))}catch(e){i(e)}}function c(e){var t;e.done?s(e.value):(t=e.value,t instanceof n?t:new n((function(e){e(t)}))).then(o,a)}c((r=r.apply(e,t||[])).next())}))}var t;"function"==typeof SuppressedError&&SuppressedError,function(e){e.GET="GET",e.POST="POST",e.PATCH="PATCH",e.DELETE="DELETE",e.LOCAL="LOCAL"}(t||(t={}));"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;function n(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var r,s,i={exports:{}}; /*! lil-uuid - v0.1 - MIT License - https://github.com/lil-js/uuid */r=i,function(e){var t="0.1.0",n={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};function r(){var e,t,n="";for(e=0;e<32;e++)t=16*Math.random()|0,8!==e&&12!==e&&16!==e&&20!==e||(n+="-"),n+=(12===e?4:16===e?3&t|8:t).toString(16);return n}function s(e,t){var r=n[t||"all"];return r&&r.test(e)||!1}r.isUUID=s,r.VERSION=t,e.uuid=r,e.isUUID=s}(s=i.exports),null!==r&&(r.exports=s.uuid);var o=n(i.exports),a={createUUID:()=>o.uuid?o.uuid():o()};const c=new Map,l={},u=a.createUUID(),d=new Map,h={},f={},p={},b={},g={},v={};self.onconnect=e=>{ae("New PubNub Client connected to the Subscription Shared Worker."),e.ports.forEach((e=>{e.start(),e.onmessage=t=>{if(!H(t))return;const n=t.data;if("client-register"===n.type)n.port=e,x(n),ae(`Client '${n.clientIdentifier}' registered with '${u}' shared worker`);else if("client-update"===n.type)W(n);else if("client-unregister"===n.type)D(n);else if("client-pong"===n.type)M(n);else if("send-request"===n.type)if(n.request.path.startsWith("/v2/subscribe")){const e=F(n),t=h[n.clientIdentifier];if(t){const r=oe(t);let s=[];if(c.has(r)&&(s=c.get(r)[0]),s.push([t,n]),c.has(r)&&e&&(clearTimeout(c.get(r)[1]),c.delete(r)),!c.has(r)){const e=setTimeout((()=>{y(s,n),c.delete(r)}),50);c.set(r,[s,e])}}}else n.request.path.endsWith("/heartbeat")?(N(n),I(n)):k(n);else"cancel-request"===n.type&&w(n)},e.postMessage({type:"shared-worker-connected"})}))};const y=(e,t)=>{const n=S(t),r=h[t.clientIdentifier];r&&(e=e.filter((e=>e[0].clientIdentifier!==r.clientIdentifier)),q(r,t,n,!0),e.forEach((([e,t])=>q(e,t,n,!1))))},q=(e,t,n,r)=>{var s;let i=!1;if(r||"string"==typeof n||(n=n.identifier),e.subscription&&(i="0"===e.subscription.timetoken),"string"==typeof n){const r=v[n];if(e){if(e.subscription&&(e.subscription.refreshTimestamp=Date.now(),e.subscription.timetoken=r.timetoken,e.subscription.region=r.region,e.subscription.serviceRequestId=n),!i)return;const o=(new TextEncoder).encode(`{"t":{"t":"${r.timetoken}","r":${null!==(s=r.region)&&void 0!==s?s:"0"}},"m":[]}`),a=new Headers({"Content-Type":'text/javascript; charset="UTF-8"',"Content-Length":`${o.length}`}),c=new Response(o,{status:200,headers:a}),l=L([c,o]);l.url=`${t.request.origin}${t.request.path}`,l.clientIdentifier=t.clientIdentifier,l.identifier=t.request.identifier,R(e,l)}return}t.request.cancellable&&d.set(n.identifier,new AbortController);const o=v[n.identifier],{timetokenOverride:a,regionOverride:c}=o,l="0"===o.timetoken;ae(`'${Object.keys(v).length}' subscription request currently active.`);for(const e of O(n.identifier))ae({messageType:"network-request",message:n},e);T(n,(()=>O(n.identifier)),((e,r,s)=>{C(e,r,s,t.request),P(e,n.identifier)}),((e,r,s)=>{C(e,r,null,t.request,U(s)),P(e,n.identifier)}),(e=>{let t=e;return l&&a&&"0"!==a&&(t=m(t,a,c)),t}))},m=(e,t,n)=>{if(void 0===t||"0"===t||e[0].status>=400)return e;let r;const s=e[0];let i=s,o=e[1];try{r=JSON.parse((new TextDecoder).decode(o))}catch(t){return ae(`Subscribe response parse error: ${t}`),e}r.t.t=t,n&&(r.t.r=parseInt(n,10));try{if(o=(new TextEncoder).encode(JSON.stringify(r)).buffer,o.byteLength){const e=new Headers(s.headers);e.set("Content-Length",`${o.byteLength}`),i=new Response(o,{status:s.status,statusText:s.statusText,headers:e})}}catch(t){return ae(`Subscribe serialization error: ${t}`),e}return o.byteLength>0?[i,o]:e},I=(e,t=!0,n=!1)=>{var r;const s=h[e.clientIdentifier],i=G(e,t,n);if(!s)return;const o=`${s.userId}_${null!==(r=se(s))&&void 0!==r?r:""}`,a=p[s.subscriptionKey],c=(null!=a?a:{})[o];if(!i){let t,n,r=`Previous heartbeat request has been sent less than ${s.heartbeatInterval} seconds ago. Skipping...`;if((!s.heartbeat||0===s.heartbeat.channels.length&&0===s.heartbeat.channelGroups.length)&&(r=`${s.clientIdentifier} doesn't have subscriptions to non-presence channels. Skipping...`),ae(r,s),c&&c.response&&([t,n]=c.response),!t){n=(new TextEncoder).encode('{ "status": 200, "message": "OK", "service": "Presence" }').buffer;const e=new Headers({"Content-Type":'text/javascript; charset="UTF-8"',"Content-Length":`${n.byteLength}`});t=new Response(n,{status:200,headers:e})}const i=L([t,n]);return i.url=`${e.request.origin}${e.request.path}`,i.clientIdentifier=e.clientIdentifier,i.identifier=e.request.identifier,void R(s,i)}ae("Started heartbeat request.",s);for(const t of Y(e))ae({messageType:"network-request",message:i},t);T(i,(()=>[s]),((t,n,r)=>{c&&(c.response=r),C(t,n,r,e.request),r[0].status>=400&&r[0].status<500&&J(s)}),((t,n,r)=>{C(t,n,null,e.request,U(r))})),n||B(s)},k=(e,t,n)=>{var r,s,i;const o=null!=t?t:h[e.clientIdentifier],a=A(e,t);if(!o)return;const{subscription:c,heartbeat:l}=o,u=null!=n?n:null==c?void 0:c.serviceRequestId;if(c&&0===c.channels.length&&0===c.channelGroups.length&&(c.channelGroupQuery="",c.path="",c.previousTimetoken="0",c.refreshTimestamp=Date.now(),c.timetoken="0",delete c.region,delete c.serviceRequestId,delete c.request),p[o.subscriptionKey]&&l&&0===l.channels.length&&0===l.channelGroups.length){const e=null!==(r=p[i=o.subscriptionKey])&&void 0!==r?r:p[i]={},t=`${o.userId}_${null!==(s=se(o))&&void 0!==s?s:""}`;e[t]&&e[t].clientIdentifier===o.clientIdentifier&&delete e[t].clientIdentifier,delete l.heartbeatEvent,J(o)}if(!a){const t=(new TextEncoder).encode('{"status": 200, "action": "leave", "message": "OK", "service":"Presence"}'),n=new Headers({"Content-Type":'text/javascript; charset="UTF-8"',"Content-Length":`${t.length}`}),r=new Response(t,{status:200,headers:n}),s=L([r,t]);return s.url=`${e.request.origin}${e.request.path}`,s.clientIdentifier=e.clientIdentifier,s.identifier=e.request.identifier,void R(o,s)}ae("Started leave request.",o);for(const n of Z(e,t))ae({messageType:"network-request",message:a},n);if(T(a,(()=>[o]),((t,n,r)=>{C(t,n,r,e.request)}),((t,n,r)=>{C(t,n,null,e.request,U(r))})),void 0===u)return;const d=O(u);d.forEach((e=>{e&&e.subscription&&delete e.subscription.serviceRequestId})),j(u),$(d)},w=e=>{const t=h[e.clientIdentifier];if(!t||!t.subscription)return;const n=t.subscription.serviceRequestId;t&&n&&(delete t.subscription.serviceRequestId,t.subscription.request&&t.subscription.request.identifier===e.identifier&&delete t.subscription.request,j(n))},$=e=>{let t,n;for(const r of e)if(r.subscription&&r.subscription.request){n=r.subscription.request,t=r;break}if(!n||!t)return;const r={type:"send-request",clientIdentifier:t.clientIdentifier,subscriptionKey:t.subscriptionKey,request:n};y([[t,r]],r)},T=(t,n,r,s,i)=>{e(void 0,void 0,void 0,(function*(){var e;const o=K(t);Promise.race([fetch(o,{signal:null===(e=d.get(t.identifier))||void 0===e?void 0:e.signal,keepalive:!0}),E(t.identifier,t.timeout)]).then((e=>e.arrayBuffer().then((t=>[e,t])))).then((e=>i?i(e):e)).then((e=>{const t=n();0!==t.length&&r(t,o,e)})).catch((e=>{const t=n();if(0===t.length)return;let r=e;if("string"==typeof e){const t=e.toLowerCase();r=new Error(e),!t.includes("timeout")&&t.includes("cancel")&&(r.name="AbortError")}s(t,o,r)}))}))},j=e=>{if(0===O(e).length){const t=d.get(e);d.delete(e),delete v[e],t&&t.abort("Cancel request")}},E=(e,t)=>new Promise(((n,r)=>{const s=setTimeout((()=>{d.delete(e),clearTimeout(s),r(new Error("Request timeout"))}),1e3*t)})),O=e=>Object.values(h).filter((t=>void 0!==t&&void 0!==t.subscription&&t.subscription.serviceRequestId===e)),P=(e,t)=>{delete v[t],e.forEach((e=>{e.subscription&&(delete e.subscription.request,delete e.subscription.serviceRequestId)}))},K=e=>{let t;const n=e.queryParameters;let r=e.path;if(e.headers){t={};for(const[n,r]of Object.entries(e.headers))t[n]=r}return n&&0!==Object.keys(n).length&&(r=`${r}?${le(n)}`),new Request(`${e.origin}${r}`,{method:e.method,headers:t,redirect:"follow"})},S=e=>{var t,n,r,s,i;const o=h[e.clientIdentifier],c=o.subscription,l=X(c.timetoken,e),u=a.createUUID(),d=Object.assign({},e.request);let f,p,g;if(l.length>1){const i=z(l,e);if(i){const e=v[i],{channels:n,channelGroups:r}=null!==(t=o.subscription)&&void 0!==t?t:{channels:[],channelGroups:[]};if((!(n.length>0)||ne(e.channels,n))&&(!(r.length>0)||ne(e.channelGroups,r)))return i}const a=(null!==(n=b[o.subscriptionKey])&&void 0!==n?n:{})[o.userId],h={},y=new Set(c.channelGroups),q=new Set(c.channels);a&&c.objectsWithState.length&&c.objectsWithState.forEach((e=>{const t=a[e];t&&(h[e]=t)}));for(const e of l){const{subscription:t}=e;if(!t)continue;if(t.timetoken){let e=!p;e||"0"===t.timetoken||("0"===p?e=!0:t.timetoken<p&&(e=t.refreshTimestamp>f)),e&&(f=t.refreshTimestamp,p=t.timetoken,g=t.region)}t.channelGroups.forEach(y.add,y),t.channels.forEach(q.add,q);const n=t.serviceRequestId;t.serviceRequestId=u,n&&v[n]&&j(n),a&&t.objectsWithState.forEach((e=>{const t=a[e];t&&!h[e]&&(h[e]=t)}))}const m=null!==(r=v[u])&&void 0!==r?r:v[u]={requestId:u,timetoken:null!==(s=d.queryParameters.tt)&&void 0!==s?s:"0",channelGroups:[],channels:[]};if(q.size){m.channels=Array.from(q).sort();const e=d.path.split("/");e[4]=m.channels.join(","),d.path=e.join("/")}if(y.size&&(m.channelGroups=Array.from(y).sort(),d.queryParameters["channel-group"]=m.channelGroups.join(",")),Object.keys(h).length&&(d.queryParameters.state=JSON.stringify(h)),d.queryParameters&&d.queryParameters.auth){const e=ie(l);e&&(d.queryParameters.auth=e)}}else v[u]={requestId:u,timetoken:null!==(i=d.queryParameters.tt)&&void 0!==i?i:"0",channelGroups:c.channelGroups,channels:c.channels};v[u]&&(d.queryParameters&&void 0!==d.queryParameters.tt&&void 0!==d.queryParameters.tr&&(v[u].region=d.queryParameters.tr),(!v[u].timetokenOverride||"0"!==v[u].timetokenOverride&&p&&"0"!==p)&&(v[u].timetokenOverride=p,v[u].regionOverride=g)),c.serviceRequestId=u,d.identifier=u;const y=l.reduce(((e,{clientIdentifier:t})=>(e.push(t),e)),[]).join(", ");if(y.length>0)for(const e of l)ce(v[u],`Started aggregated request for clients: ${y}`,e);return d},G=(e,t,n)=>{var r,s,i,o,a;const c=h[e.clientIdentifier],l=Y(e),u=Object.assign({},e.request);if(!c||!c.heartbeat)return;const d=null!==(r=p[a=c.subscriptionKey])&&void 0!==r?r:p[a]={},f=`${c.userId}_${null!==(s=se(c))&&void 0!==s?s:""}`,b=[...c.heartbeat.channelGroups],g=[...c.heartbeat.channels];let v,y,q=!1;if(d[f]){const{createdByActualRequest:e,channels:r,channelGroups:s,response:i}=d[f];!e&&t&&(d[f].createdByActualRequest=!0,d[f].timestamp=Date.now(),n=!0),v=null!==(o=c.heartbeat.presenceState)&&void 0!==o?o:{},y=ne(r,g)&&ne(s,b),i&&(q=i[0].status>=400)}else d[f]={createdByActualRequest:t,channels:g,channelGroups:b,clientIdentifier:c.clientIdentifier,timestamp:Date.now()},v=null!==(i=c.heartbeat.presenceState)&&void 0!==i?i:{},y=!1;let m=c.heartbeatInterval;for(const e of l)e.heartbeatInterval&&(m=Math.min(m,e.heartbeatInterval));if(y&&d[f].clientIdentifier){const e=d[f].timestamp+1e3*m,t=Date.now();if(!n&&!q&&t<e){const n=.05*m*1e3;if(m-n<=3||e-t>n)return void B(c,!0)}}delete d[f].response,d[f].clientIdentifier=c.clientIdentifier;for(const t of l){const{heartbeat:n}=t;void 0!==n&&t.clientIdentifier!==e.clientIdentifier&&(n.presenceState&&(v=Object.assign(Object.assign({},v),n.presenceState)),b.push(...n.channelGroups.filter((e=>!b.includes(e)))),g.push(...n.channels.filter((e=>!g.includes(e)))))}d[f].channels=g,d[f].channelGroups=b,n||(d[f].timestamp=Date.now());for(const e in Object.keys(v))g.includes(e)||b.includes(e)||delete v[e];if(0!==g.length||0!==b.length){if(g.length||b.length){const e=u.path.split("/");e[6]=g.length?g.join(","):",",u.path=e.join("/")}if(b.length&&(u.queryParameters["channel-group"]=b.join(",")),Object.keys(v).length?u.queryParameters.state=JSON.stringify(v):delete u.queryParameters.state,l.length>1&&u.queryParameters&&u.queryParameters.auth){const e=ie(l);e&&(u.queryParameters.auth=e)}return u}},A=(e,t)=>{var n;const r=null!=t?t:h[e.clientIdentifier],s=Z(e,t);let i=te(e.request),o=ee(e.request);const a=Object.assign({},e.request);if(r&&r.subscription){const{subscription:e}=r;if(o.length){e.channels=e.channels.filter((e=>!o.includes(e)));const t=e.path.split("/");if(","!==t[4]){const n=t[4].split(",").filter((e=>!o.includes(e)));t[4]=n.length?n.join(","):",",e.path=t.join("/")}}if(i.length&&(e.channelGroups=e.channelGroups.filter((e=>!i.includes(e))),e.channelGroupQuery.length>0)){const t=e.channelGroupQuery.split(",").filter((e=>!i.includes(e)));e.channelGroupQuery=t.length?t.join(","):""}}if(r&&r.heartbeat){const{heartbeat:e}=r;o.length&&(e.channels=e.channels.filter((e=>!o.includes(e)))),i.length&&(e.channelGroups=e.channelGroups.filter((e=>!i.includes(e))))}for(const t of s){const n=t.subscription;void 0!==n&&(t.clientIdentifier!==e.clientIdentifier&&(o.length&&(o=o.filter((e=>!e.endsWith("-pnpres")&&!n.channels.includes(e)))),i.length&&(i=i.filter((e=>!e.endsWith("-pnpres")&&!n.channelGroups.includes(e))))))}const c=o.length+i.length;if(o.length&&(o=o.filter((e=>!e.endsWith("-pnpres")))),i.length&&(i=i.filter((e=>!e.endsWith("-pnpres")))),0!==o.length||0!==i.length){if(r&&p[r.subscriptionKey]&&(o.length||i.length)){const e=p[r.subscriptionKey],t=`${r.userId}_${null!==(n=se(r))&&void 0!==n?n:""}`;if(e[t]){let{channels:n,channelGroups:r}=e[t];i.length&&(r=r.filter((e=>!o.includes(e)))),o.length&&(n=n.filter((e=>!o.includes(e)))),e[t].channelGroups=r,e[t].channels=n}}if(o.length){const e=a.path.split("/");e[6]=o.join(","),a.path=e.join("/")}if(i.length&&(a.queryParameters["channel-group"]=i.join(",")),s.length>1&&a.queryParameters&&a.queryParameters.auth){const e=ie(s);e&&(a.queryParameters.auth=e)}return a}if(r&&r.workerLogVerbosity){const e=s.reduce(((e,{clientIdentifier:t})=>(e.push(t),e)),[]).join(", ");ae(c>0?"Leaving only presence channels which doesn't require presence leave. Ignoring leave request.":`Specified channels and groups still in use by other clients: ${e}. Ignoring leave request.`,r)}},R=(e,t)=>{var n;const r=(null!==(n=g[e.subscriptionKey])&&void 0!==n?n:{})[e.clientIdentifier];if(!r)return!1;try{return r.postMessage(t),!0}catch(t){e.workerLogVerbosity&&console.error(`[SharedWorker] Unable send message using message port: ${t}`)}return!1},C=(e,t,n,r,s)=>{var i,o;if(0===e.length)return;if(!s&&!n)return;const a=e.some((e=>e&&e.workerLogVerbosity)),c=null!==(i=g[e[0].subscriptionKey])&&void 0!==i?i:{},l=r.path.startsWith("/v2/subscribe");!s&&n&&(s=n[0].status>=400?U(void 0,n):L(n));const u={};let d,h=200;if(n){d=n[1].byteLength>0?n[1]:void 0;const{headers:e}=n[0];h=n[0].status,e.forEach(((e,t)=>u[t]=e.toLowerCase()))}const f={status:h,url:t.url,headers:u,body:d};if(a&&r&&!r.path.endsWith("/heartbeat")){const t=`Notify clients about ${l?"subscribe":"leave"} request completion: ${e.reduce(((e,{clientIdentifier:t})=>(e.push(t),e)),[]).join(", ")}`;for(const n of e)ae(t,n)}for(const t of e){if(l&&!t.subscription){if(a){const n=`${t.clientIdentifier} doesn't have active subscription. Don't notify about completion.`;for(const t of e)ae(n,t)}continue}const n=c[t.clientIdentifier],{request:i}=null!==(o=t.subscription)&&void 0!==o?o:{};let u=null!=i?i:r;if(l||(u=r),n&&u){const e=Object.assign(Object.assign({},s),{clientIdentifier:t.clientIdentifier,identifier:u.identifier,url:`${u.origin}${u.path}`});if("request-process-success"===s.type&&t.workerLogVerbosity)ae({messageType:"network-response",message:f},t);else if("request-process-error"===s.type&&t.workerLogVerbosity){const n=!!s.error&&("TIMEOUT"===s.error.type||"ABORTED"===s.error.type);let i=s.error?s.error.message:"Unknown";if(e.response){const t=e.response.headers["content-type"];if(e.response.body&&t&&(-1!==t.indexOf("javascript")||-1!==t.indexOf("json")))try{const t=JSON.parse((new TextDecoder).decode(e.response.body));"message"in t?i=t.message:"error"in t&&("string"==typeof t.error?i=t.error:"object"==typeof t.error&&"message"in t.error&&(i=t.error.message))}catch(e){}"Unknown"===i&&(i=e.response.status>=500?"Internal Server Error":400==e.response.status?"Bad request":403==e.response.status?"Access denied":`${e.response.status}`)}ae({messageType:"network-request",message:r,details:i,canceled:n,failed:!n},t)}R(t,e)}else if(!n&&a){const n=`${t.clientIdentifier} doesn't have Shared Worker's communication channel. Don't notify about completion.`;for(const r of e)r.clientIdentifier!==t.clientIdentifier&&ae(n,r)}}},L=e=>{var t;const[n,r]=e,s=r.byteLength>0?r:void 0,i=parseInt(null!==(t=n.headers.get("Content-Length"))&&void 0!==t?t:"0",10),o=n.headers.get("Content-Type"),a={};return n.headers.forEach(((e,t)=>a[t]=e.toLowerCase())),{type:"request-process-success",clientIdentifier:"",identifier:"",url:"",response:{contentLength:i,contentType:o,headers:a,status:n.status,body:s}}},U=(e,t)=>{if(t)return Object.assign(Object.assign({},L(t)),{type:"request-process-error"});let n="NETWORK_ISSUE",r="Unknown error",s="Error";e&&e instanceof Error&&(r=e.message,s=e.name);const i=r.toLowerCase();return i.includes("timeout")?n="TIMEOUT":("AbortError"===s||i.includes("aborted")||i.includes("cancel"))&&(r="Request aborted",n="ABORTED"),{type:"request-process-error",clientIdentifier:"",identifier:"",url:"",error:{name:s,type:n,message:r}}},x=e=>{var t,n,r,s,i;const{clientIdentifier:o}=e;if(h[o])return;const a=h[o]={clientIdentifier:o,subscriptionKey:e.subscriptionKey,userId:e.userId,heartbeatInterval:e.heartbeatInterval,newlyRegistered:!0,offlineClientsCheckInterval:e.workerOfflineClientsCheckInterval,unsubscribeOfflineClients:e.workerUnsubscribeOfflineClients,workerLogVerbosity:e.workerLogVerbosity},c=null!==(t=f[s=e.subscriptionKey])&&void 0!==t?t:f[s]=[];c.every((e=>e.clientIdentifier!==o))&&c.push(a),(null!==(n=g[i=e.subscriptionKey])&&void 0!==n?n:g[i]={})[o]=e.port;const u=`Registered PubNub client with '${o}' identifier. '${c.length}' clients currently active.`;for(const e of c)ae(u,e);if(!l[e.subscriptionKey]&&(null!==(r=f[e.subscriptionKey])&&void 0!==r?r:[]).length>0){const{subscriptionKey:t}=e,n=e.workerOfflineClientsCheckInterval;for(const e of c)ae(`Setup PubNub client ping event ${n} seconds`,e);l[t]=setTimeout((()=>re(t)),500*n-1)}},W=e=>{var t,n,r;const{clientIdentifier:s,userId:i,heartbeatInterval:o,accessToken:a,preProcessedToken:c}=e,l=h[s];if(!l)return;if(ce({userId:i,heartbeatInterval:o,authKey:a,token:c},"Update client configuration:",l),i!==l.userId||a&&a!==(null!==(t=l.authKey)&&void 0!==t?t:"")){const e=null!==(n=p[l.subscriptionKey])&&void 0!==n?n:{},t=`${i}_${null!==(r=se(l))&&void 0!==r?r:""}`;void 0!==e[t]&&delete e[t]}const u=l.heartbeatInterval!==o;l.userId=i,l.heartbeatInterval=o,a&&(l.authKey=a),c&&(l.accessToken=c),u&&B(l,!0),Q(l),l.heartbeat&&l.heartbeat.heartbeatEvent&&I(l.heartbeat.heartbeatEvent,!1,!0)},D=e=>{V(e.subscriptionKey,e.clientIdentifier)},F=e=>{var t,n,r,s,i,o,a,c,l,u,d,f,p,g,v,y,q,m,I,k;const w=e.request.queryParameters,{clientIdentifier:$}=e,T=h[$];let j=!1;if(!T)return;const E=null!==(t=w["channel-group"])&&void 0!==t?t:"",O=null!==(n=w.state)&&void 0!==n?n:"";let P=T.subscription;if(P){if(O.length>0){const e=JSON.parse(O),t=null!==(o=(y=null!==(i=b[v=T.subscriptionKey])&&void 0!==i?i:b[v]={})[q=T.userId])&&void 0!==o?o:y[q]={};Object.entries(e).forEach((([e,n])=>t[e]=n));for(const n of P.objectsWithState)e[n]||delete t[n];P.objectsWithState=Object.keys(e)}else if(P.objectsWithState.length){const e=null!==(c=(I=null!==(a=b[m=T.subscriptionKey])&&void 0!==a?a:b[m]={})[k=T.userId])&&void 0!==c?c:I[k]={};for(const t of P.objectsWithState)delete e[t];P.objectsWithState=[]}}else{if(j=!0,P={refreshTimestamp:0,path:"",channelGroupQuery:"",channels:[],channelGroups:[],previousTimetoken:"0",timetoken:"0",objectsWithState:[]},O.length>0){const e=JSON.parse(O),t=null!==(s=(p=null!==(r=b[f=T.subscriptionKey])&&void 0!==r?r:b[f]={})[g=T.userId])&&void 0!==s?s:p[g]={};Object.entries(e).forEach((([e,n])=>t[e]=n)),P.objectsWithState=Object.keys(e)}T.subscription=P}if(P.path!==e.request.path){P.path=e.request.path;const t=ee(e.request);j||(j=!ne(P.channels,t)),P.channels=t}if(P.channelGroupQuery!==E){P.channelGroupQuery=E;const t=te(e.request);j||(j=!ne(P.channelGroups,t)),P.channelGroups=t}let{authKey:K}=T;return P.refreshTimestamp=Date.now(),P.request=e.request,P.filterExpression=null!==(l=w["filter-expr"])&&void 0!==l?l:"",P.timetoken=null!==(u=w.tt)&&void 0!==u?u:"0",void 0!==w.tr&&(P.region=w.tr),T.authKey=null!==(d=w.auth)&&void 0!==d?d:"",T.origin=e.request.origin,T.userId=w.uuid,T.pnsdk=w.pnsdk,T.accessToken=e.preProcessedToken,T.newlyRegistered&&!K&&T.authKey&&(K=T.authKey),T.newlyRegistered=!1,j},N=e=>{var t,n,r;const{clientIdentifier:s}=e,i=h[s],{request:o}=e,a=null!==(t=o.queryParameters)&&void 0!==t?t:{};if(!i)return;const c=null!==(n=i.heartbeat)&&void 0!==n?n:i.heartbeat={channels:[],channelGroups:[]};c.heartbeatEvent=Object.assign({},e),c.channelGroups=te(o).filter((e=>!e.endsWith("-pnpres"))),c.channels=ee(o).filter((e=>!e.endsWith("-pnpres")));const l=null!==(r=a.state)&&void 0!==r?r:"";if(l.length>0){const e=JSON.parse(l);for(const t of Object.keys(e))c.channels.includes(t)||c.channelGroups.includes(t)||delete e[t];c.presenceState=e}i.accessToken=e.preProcessedToken},M=e=>{const t=h[e.clientIdentifier];t&&(t.lastPongEvent=(new Date).getTime()/1e3)},V=(e,t)=>{var n,r,s;const i=h[t];delete h[t];let o,a=f[e];if(i){if(i.subscription&&(o=i.subscription.serviceRequestId,delete i.subscription.serviceRequestId,o&&j(o)),J(i),p[e]){const t=null!==(n=p[e])&&void 0!==n?n:p[e]={},s=`${i.userId}_${null!==(r=se(i))&&void 0!==r?r:""}`;t[s]&&t[s].clientIdentifier===i.clientIdentifier&&delete t[s].clientIdentifier}i.unsubscribeOfflineClients&&_(i,o)}if(a)if(a=a.filter((e=>e.clientIdentifier!==t)),a.length>0?f[e]=a:(delete f[e],delete p[e]),0===a.length&&delete b[e],a.length>0){const n=g[e];n&&(delete n[t],0===Object.keys(n).length&&delete g[e])}else delete g[e];const c=`Invalidate '${t}' client. '${(null!==(s=f[e])&&void 0!==s?s:[]).length}' clients currently active.`;if(a)for(const e of a)ae(c,e);else ae(c)},_=(e,n)=>{if(!e.subscription)return;const{channels:r,channelGroups:s}=e.subscription,i=(null!=s?s:[]).filter((e=>!e.endsWith("-pnpres"))).map((e=>ue(e))).sort(),o=(null!=r?r:[]).filter((e=>!e.endsWith("-pnpres"))).map((e=>ue(e))).sort();if(0===o.length&&0===i.length)return;const c=i.length>0?i.join(","):void 0,l=0===o.length?",":o.join(","),u=Object.assign(Object.assign({instanceid:e.clientIdentifier,uuid:e.userId,requestid:a.createUUID()},e.authKey?{auth:e.authKey}:{}),c?{"channel-group":c}:{}),d={type:"send-request",clientIdentifier:e.clientIdentifier,subscriptionKey:e.subscriptionKey,request:{origin:e.origin,path:`/v2/presence/sub-key/${e.subscriptionKey}/channel/${l}/leave`,queryParameters:u,method:t.GET,headers:{},timeout:10,cancellable:!1,compressible:!1,identifier:u.requestid}};k(d,e,n)},B=(e,t=!1)=>{const{heartbeat:n,heartbeatInterval:r}=e;if(!(r&&r>0&&void 0!==n&&n.heartbeatEvent&&(n.channels.length>0||n.channelGroups.length>0)))return void J(e);if(t&&!n.loop)return;let s=r;if(t&&n.loop){const e=(Date.now()-n.loop.startTimestamp)/1e3;e<s&&(s-=e),s===n.loop.heartbeatInterval&&(s+=.05)}J(e),s<=0||(n.loop={timer:setTimeout((()=>{if(J(e),!e.heartbeat||!e.heartbeat.heartbeatEvent)return;const{request:t}=e.heartbeat.heartbeatEvent;t.identifier=a.createUUID(),t.queryParameters.requestid=t.identifier,I(e.heartbeat.heartbeatEvent,!1)}),1e3*s),heartbeatInterval:r,startTimestamp:Date.now()})},J=e=>{const{heartbeat:t}=e;void 0!==t&&t.loop&&(clearTimeout(t.loop.timer),delete t.loop)},Q=e=>{var t,n,r;const{subscription:s,heartbeat:i}=e;if(s&&s.request&&s.request.queryParameters){const t=s.request.queryParameters;e.authKey&&e.authKey.length>0?t.auth=e.authKey:t.auth&&delete t.auth}if((null==i?void 0:i.heartbeatEvent)&&i.heartbeatEvent.request){e.accessToken&&(i.heartbeatEvent.preProcessedToken=e.accessToken);const s=null!==(t=p[r=e.subscriptionKey])&&void 0!==t?t:p[r]={},o=`${e.userId}_${null!==(n=se(e))&&void 0!==n?n:""}`;s[o]&&s[o].response&&delete s[o].response,i.heartbeatEvent.request.identifier=a.createUUID();const c=i.heartbeatEvent.request.queryParameters;c.requestid=i.heartbeatEvent.request.identifier,e.authKey&&e.authKey.length>0?c.auth=e.authKey:c.auth&&delete c.auth}},H=e=>{const{clientIdentifier:t,subscriptionKey:n}=e.data;return!(!t||"string"!=typeof t)&&!(!n||"string"!=typeof n)},z=(e,t)=>{var n;const r=null!==(n=t.request.queryParameters["channel-group"])&&void 0!==n?n:"",s=t.request.path;let i,o;for(const n of e){const{subscription:e}=n;if(!e||!e.serviceRequestId)continue;const a=h[t.clientIdentifier],c=e.serviceRequestId;if(e.path===s&&e.channelGroupQuery===r)return ae(`Found identical request started by '${n.clientIdentifier}' client. \nWaiting for existing '${c}' request completion.`,a),e.serviceRequestId;{const r=v[e.serviceRequestId];if(i||(i=te(t.request)),o||(o=ee(t.request)),o.length&&!ne(r.channels,o))continue;if(i.length&&!ne(r.channelGroups,i))continue;return ce(r,`'${t.request.identifier}' request channels and groups are subset of ongoing '${c}' request \nwhich has started by '${n.clientIdentifier}' client. Waiting for existing '${c}' request completion.`,a),e.serviceRequestId}}},X=(e,t)=>{var n,r;const s=h[t.clientIdentifier];if(!s)return[];const i=t.request.queryParameters,o=se(s),a=null!==(n=i["filter-expr"])&&void 0!==n?n:"",c=i.uuid;return(null!==(r=f[t.subscriptionKey])&&void 0!==r?r:[]).filter((t=>t.userId===c&&se(t)===o&&t.subscription&&(0!==t.subscription.channels.length||0!==t.subscription.channelGroups.length)&&t.subscription.filterExpression===a&&("0"===e||"0"===t.subscription.timetoken||t.subscription.timetoken===e)))},Y=e=>Z(e),Z=(e,t)=>{var n;const r=null!=t?t:h[e.clientIdentifier];if(!r)return[];const s=e.request.queryParameters,i=se(r),o=s.uuid;return(null!==(n=f[e.subscriptionKey])&&void 0!==n?n:[]).filter((e=>e.userId===o&&se(e)===i))},ee=e=>{const t=e.path.split("/")[e.path.startsWith("/v2/subscribe/")?4:6];return","===t?[]:t.split(",").filter((e=>e.length>0))},te=e=>{var t;const n=null!==(t=e.queryParameters["channel-group"])&&void 0!==t?t:"";return 0===n.length?[]:n.split(",").filter((e=>e.length>0))},ne=(e,t)=>{const n=new Set(e);return t.every(n.has,n)},re=e=>{const t={type:"shared-worker-ping"},n=Object.values(h).filter((t=>t&&t.subscriptionKey===e));if(n.forEach((e=>{let r=!1;if(e&&e.lastPingRequest){const t=e.offlineClientsCheckInterval;if(!e.lastPongEvent||Math.abs(e.lastPongEvent-e.lastPingRequest)>.5*t){r=!0;for(const t of n)ae(`'${e.clientIdentifier}' client is inactive. Invalidating...`,t);V(e.subscriptionKey,e.clientIdentifier)}}e&&!r&&(e.lastPingRequest=(new Date).getTime()/1e3,R(e,t))})),n&&n.length>0&&n[0]){const t=n[0].offlineClientsCheckInterval;l[e]=setTimeout((()=>re(e)),500*t-1)}},se=e=>{var t;return e.accessToken&&null!==(t=e.accessToken.token)&&void 0!==t?t:e.authKey},ie=e=>{const t=e.filter((e=>!!e.accessToken)).sort(((e,t)=>e.accessToken.expiration-t.accessToken.expiration)).pop();return t?t.authKey:void 0},oe=e=>{const t=se(e);let n=`${e.userId}-${e.subscriptionKey}${t?`-${t}`:""}`;return e.subscription&&e.subscription.filterExpression&&(n+=`-${e.subscription.filterExpression}`),n},ae=(e,t)=>{const n=(t?[t]:Object.values(h)).filter((e=>e&&e.workerLogVerbosity)),r={type:"shared-worker-console-log",message:e};n.forEach((e=>{e&&R(e,r)}))},ce=(e,t,n)=>{const r=(n?[n]:Object.values(h)).filter((e=>e&&e.workerLogVerbosity)),s={type:"shared-worker-console-dir",message:t,data:e};r.forEach((e=>{e&&R(e,s)}))},le=e=>Object.keys(e).map((t=>{const n=e[t];return Array.isArray(n)?n.map((e=>`${t}=${ue(e)}`)).join("&"):`${t}=${ue(n)}`})).join("&"),ue=e=>encodeURIComponent(e).replace(/[!~*'()]/g,(e=>`%${e.charCodeAt(0).toString(16).toUpperCase()}`))}));