@supabase/phoenix 0.1.0 → 0.2.0
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/package.json +1 -1
- package/priv/static/phoenix.cjs.js +20 -5
- package/priv/static/phoenix.cjs.js.map +3 -3
- package/priv/static/phoenix.js +20 -5
- package/priv/static/phoenix.min.js +2 -2
- package/priv/static/phoenix.mjs +20 -5
- package/priv/static/phoenix.mjs.map +3 -3
- package/priv/static/types/socket.d.ts +6 -0
- package/priv/static/types/socket.d.ts.map +1 -1
package/priv/static/phoenix.js
CHANGED
|
@@ -1230,7 +1230,7 @@ var Phoenix = (() => {
|
|
|
1230
1230
|
this.pageHidden = true;
|
|
1231
1231
|
} else {
|
|
1232
1232
|
this.pageHidden = false;
|
|
1233
|
-
if (!this.isConnected()) {
|
|
1233
|
+
if (!this.isConnected() && !this.closeWasClean) {
|
|
1234
1234
|
this.teardown(() => this.connect());
|
|
1235
1235
|
}
|
|
1236
1236
|
}
|
|
@@ -1459,6 +1459,19 @@ var Phoenix = (() => {
|
|
|
1459
1459
|
});
|
|
1460
1460
|
return true;
|
|
1461
1461
|
}
|
|
1462
|
+
/**
|
|
1463
|
+
* @private
|
|
1464
|
+
*
|
|
1465
|
+
* @param {Function}
|
|
1466
|
+
*/
|
|
1467
|
+
transportName(transport) {
|
|
1468
|
+
switch (transport) {
|
|
1469
|
+
case LongPoll:
|
|
1470
|
+
return "LongPoll";
|
|
1471
|
+
default:
|
|
1472
|
+
return transport.name;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1462
1475
|
/**
|
|
1463
1476
|
* @private
|
|
1464
1477
|
*/
|
|
@@ -1488,14 +1501,15 @@ var Phoenix = (() => {
|
|
|
1488
1501
|
let established = false;
|
|
1489
1502
|
let primaryTransport = true;
|
|
1490
1503
|
let openRef, errorRef;
|
|
1504
|
+
let fallbackTransportName = this.transportName(fallbackTransport);
|
|
1491
1505
|
let fallback = (reason) => {
|
|
1492
|
-
this.log("transport", `falling back to ${
|
|
1506
|
+
this.log("transport", `falling back to ${fallbackTransportName}...`, reason);
|
|
1493
1507
|
this.off([openRef, errorRef]);
|
|
1494
1508
|
primaryTransport = false;
|
|
1495
1509
|
this.replaceTransport(fallbackTransport);
|
|
1496
1510
|
this.transportConnect();
|
|
1497
1511
|
};
|
|
1498
|
-
if (this.getSession(`phx:fallback:${
|
|
1512
|
+
if (this.getSession(`phx:fallback:${fallbackTransportName}`)) {
|
|
1499
1513
|
return fallback("memorized");
|
|
1500
1514
|
}
|
|
1501
1515
|
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
|
|
@@ -1512,10 +1526,11 @@ var Phoenix = (() => {
|
|
|
1512
1526
|
this.fallbackRef = this.onOpen(() => {
|
|
1513
1527
|
established = true;
|
|
1514
1528
|
if (!primaryTransport) {
|
|
1529
|
+
let fallbackTransportName2 = this.transportName(fallbackTransport);
|
|
1515
1530
|
if (!this.primaryPassedHealthCheck) {
|
|
1516
|
-
this.storeSession(`phx:fallback:${
|
|
1531
|
+
this.storeSession(`phx:fallback:${fallbackTransportName2}`, "true");
|
|
1517
1532
|
}
|
|
1518
|
-
return this.log("transport", `established ${
|
|
1533
|
+
return this.log("transport", `established ${fallbackTransportName2} fallback`);
|
|
1519
1534
|
}
|
|
1520
1535
|
clearTimeout(this.fallbackTimer);
|
|
1521
1536
|
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var Phoenix=(()=>{var L=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var I=(a,e)=>{for(var t in e)L(a,t,{get:e[t],enumerable:!0})},F=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of U(e))!D.call(a,s)&&s!==t&&L(a,s,{get:()=>e[s],enumerable:!(i=M(e,s))||i.enumerable});return a};var J=a=>F(L({},"__esModule",{value:!0}),a);var N=(a,e,t)=>new Promise((i,s)=>{var o=h=>{try{r(t.next(h))}catch(l){s(l)}},n=h=>{try{r(t.throw(h))}catch(l){s(l)}},r=h=>h.done?i(h.value):Promise.resolve(h.value).then(o,n);r((t=t.apply(a,e)).next())});var K={};I(K,{Channel:()=>v,LongPoll:()=>m,Presence:()=>w,Push:()=>T,Serializer:()=>y,Socket:()=>_,Timer:()=>b});var k=a=>typeof a=="function"?a:function(){return a};var z=typeof self!="undefined"?self:null,R=typeof window!="undefined"?window:null,d=z||R||globalThis,O="2.0.0",B=1e4,P=1e3,p={connecting:0,open:1,closing:2,closed:3},u={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},g={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},j={longpoll:"longpoll",websocket:"websocket"},$={complete:4},A="base64url.bearer.phx.";var T=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1,this.ref=void 0}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}destroy(){this.cancelRefEvent(),this.cancelTimeout()}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}};var b=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=void 0,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}};var v=class{constructor(e,t,i){this.state=u.closed,this.topic=e,this.params=k(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new T(this,g.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new b(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=u.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",s=>{this.state=u.errored,this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic}`),this.state=u.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic}`,this.joinPush.timeout),new T(this,g.leave,k({}),this.timeout).send(),this.state=u.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(g.reply,(s,o)=>{this.trigger(this.replyEventName(o),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}teardown(){this.pushBuffer.forEach(e=>e.destroy()),this.pushBuffer=[],this.rejoinTimer.reset(),this.joinPush.destroy(),this.state=u.closed,this.bindings={}}onClose(e){this.on(g.close,e)}onError(e){return this.on(g.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t=="undefined"||t===i.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,i=this.timeout){if(t=t||{},!this.joinedOnce)throw new Error(`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`);let s=new T(this,e,function(){return t},i);return this.canPush()?s.send():(s.startTimeout(),this.pushBuffer.push(s)),s}leave(e=this.timeout){this.rejoinTimer.reset(),this.joinPush.cancelTimeout(),this.state=u.leaving;let t=()=>{this.socket.hasLogger()&&this.socket.log("channel",`leave ${this.topic}`),this.trigger(g.close,"leave")},i=new T(this,g.leave,k({}),e);return i.receive("ok",()=>t()).receive("timeout",()=>t()),i.send(),this.canPush()||i.trigger("ok",{}),i}onMessage(e,t,i){return t}filterBindings(e,t,i){return!0}isMember(e,t,i,s){return this.topic!==e?!1:s&&s!==this.joinRef()?(this.socket.hasLogger()&&this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:i,joinRef:s}),!1):!0}joinRef(){return this.joinPush.ref}rejoin(e=this.timeout){this.isLeaving()||(this.socket.leaveOpenTopic(this.topic),this.state=u.joining,this.joinPush.resend(e))}trigger(e,t,i,s){let o=this.onMessage(e,t,i,s);if(t&&!o)throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");let n=this.bindings.filter(r=>r.event===e&&this.filterBindings(r,t,i));for(let r=0;r<n.length;r++)n[r].callback(o,i,s||this.joinRef())}replyEventName(e){return`chan_reply_${e}`}isClosed(){return this.state===u.closed}isErrored(){return this.state===u.errored}isJoined(){return this.state===u.joined}isJoining(){return this.state===u.joining}isLeaving(){return this.state===u.leaving}};var C=class{static request(e,t,i,s,o,n,r){if(d.XDomainRequest){let h=new d.XDomainRequest;return this.xdomainRequest(h,e,t,s,o,n,r)}else if(d.XMLHttpRequest){let h=new d.XMLHttpRequest;return this.xhrRequest(h,e,t,i,s,o,n,r)}else{if(d.fetch&&d.AbortController)return this.fetchRequest(e,t,i,s,o,n,r);throw new Error("No suitable XMLHttpRequest implementation found")}}static fetchRequest(e,t,i,s,o,n,r){let h={method:e,headers:i,body:s},l=null;if(o){l=new AbortController;let c=setTimeout(()=>l.abort(),o);h.signal=l.signal}return d.fetch(t,h).then(c=>c.text()).then(c=>this.parseJSON(c)).then(c=>r&&r(c)).catch(c=>{c.name==="AbortError"&&n?n():r&&r(null)}),l}static xdomainRequest(e,t,i,s,o,n,r){return e.timeout=o,e.open(t,i),e.onload=()=>{let h=this.parseJSON(e.responseText);r&&r(h)},n&&(e.ontimeout=n),e.onprogress=()=>{},e.send(s),e}static xhrRequest(e,t,i,s,o,n,r,h){e.open(t,i,!0),e.timeout=n;for(let[l,c]of Object.entries(s))e.setRequestHeader(l,c);return e.onerror=()=>h&&h(null),e.onreadystatechange=()=>{if(e.readyState===$.complete&&h){let l=this.parseJSON(e.responseText);h(l)}},r&&(e.ontimeout=r),e.send(o),e}static parseJSON(e){if(!e||e==="")return null;try{return JSON.parse(e)}catch(t){return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let i=[];for(var s in e){if(!Object.prototype.hasOwnProperty.call(e,s))continue;let o=t?`${t}[${s}]`:s,n=e[s];typeof n=="object"?i.push(this.serialize(n,o)):i.push(encodeURIComponent(o)+"="+encodeURIComponent(n))}return i.join("&")}static appendParams(e,t){if(Object.keys(t).length===0)return e;let i=e.match(/\?/)?"&":"?";return`${e}${i}${this.serialize(t)}`}};var W=a=>{let e="",t=new Uint8Array(a),i=t.byteLength;for(let s=0;s<i;s++)e+=String.fromCharCode(t[s]);return btoa(e)},m=class{constructor(e,t){t&&t.length===2&&t[1].startsWith(A)&&(this.authToken=atob(t[1].slice(A.length))),this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.reqs=new Set,this.awaitingBatchAck=!1,this.currentBatch=null,this.currentBatchTimer=null,this.batchBuffer=[],this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=p.connecting,setTimeout(()=>this.poll(),0)}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+j.websocket),"$1/"+j.longpoll)}endpointURL(){return C.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(e,t,i){this.close(e,t,i),this.readyState=p.connecting}ontimeout(){this.onerror("timeout"),this.closeAndRetry(1005,"timeout",!1)}isActive(){return this.readyState===p.open||this.readyState===p.connecting}poll(){let e={Accept:"application/json"};this.authToken&&(e["X-Phoenix-AuthToken"]=this.authToken),this.ajax("GET",e,null,()=>this.ontimeout(),t=>{if(t){var{status:i,token:s,messages:o}=t;if(i===410&&this.token!==null){this.onerror(410),this.closeAndRetry(3410,"session_gone",!1);return}this.token=s}else i=0;switch(i){case 200:o.forEach(n=>{setTimeout(()=>this.onmessage({data:n}),0)}),this.poll();break;case 204:this.poll();break;case 410:this.readyState=p.open,this.onopen({}),this.poll();break;case 403:this.onerror(403),this.close(1008,"forbidden",!1);break;case 0:case 500:this.onerror(500),this.closeAndRetry(1011,"internal server error",500);break;default:throw new Error(`unhandled poll status ${i}`)}})}send(e){typeof e!="string"&&(e=W(e)),this.currentBatch?this.currentBatch.push(e):this.awaitingBatchAck?this.batchBuffer.push(e):(this.currentBatch=[e],this.currentBatchTimer=setTimeout(()=>{this.batchSend(this.currentBatch),this.currentBatch=null},0))}batchSend(e){this.awaitingBatchAck=!0,this.ajax("POST",{"Content-Type":"application/x-ndjson"},e.join(`
|
|
2
|
-
`),()=>this.onerror("timeout"),t=>{this.awaitingBatchAck=!1,!t||t.status!==200?(this.onerror(t&&t.status),this.closeAndRetry(1011,"internal server error",!1)):this.batchBuffer.length>0&&(this.batchSend(this.batchBuffer),this.batchBuffer=[])})}close(e,t,i){for(let o of this.reqs)o.abort();this.readyState=p.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});this.batchBuffer=[],clearTimeout(this.currentBatchTimer),this.currentBatchTimer=null,typeof CloseEvent!="undefined"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s,o){let n,r=()=>{this.reqs.delete(n),s()};n=C.request(e,this.endpointURL(),t,i,this.timeout,r,h=>{this.reqs.delete(n),this.isActive()&&o(h)}),this.reqs.add(n)}};var w=class a{constructor(e,t={}){let i=t.events||{state:"presence_state",diff:"presence_diff"};this.state={},this.pendingDiffs=[],this.channel=e,this.joinRef=null,this.caller={onJoin:function(){},onLeave:function(){},onSync:function(){}},this.channel.on(i.state,s=>{let{onJoin:o,onLeave:n,onSync:r}=this.caller;this.joinRef=this.channel.joinRef(),this.state=a.syncState(this.state,s,o,n),this.pendingDiffs.forEach(h=>{this.state=a.syncDiff(this.state,h,o,n)}),this.pendingDiffs=[],r()}),this.channel.on(i.diff,s=>{let{onJoin:o,onLeave:n,onSync:r}=this.caller;this.inPendingSyncState()?this.pendingDiffs.push(s):(this.state=a.syncDiff(this.state,s,o,n),r())})}onJoin(e){this.caller.onJoin=e}onLeave(e){this.caller.onLeave=e}onSync(e){this.caller.onSync=e}list(e){return a.list(this.state,e)}inPendingSyncState(){return!this.joinRef||this.joinRef!==this.channel.joinRef()}static syncState(e,t,i,s){let o=this.clone(e),n={},r={};return this.map(o,(h,l)=>{t[h]||(r[h]=l)}),this.map(t,(h,l)=>{let c=o[h];if(c){let f=l.metas.map(E=>E.phx_ref),S=c.metas.map(E=>E.phx_ref),x=l.metas.filter(E=>S.indexOf(E.phx_ref)<0),H=c.metas.filter(E=>f.indexOf(E.phx_ref)<0);x.length>0&&(n[h]=l,n[h].metas=x),H.length>0&&(r[h]=this.clone(c),r[h].metas=H)}else n[h]=l}),this.syncDiff(o,{joins:n,leaves:r},i,s)}static syncDiff(e,t,i,s){let{joins:o,leaves:n}=this.clone(t);return i||(i=function(){}),s||(s=function(){}),this.map(o,(r,h)=>{let l=e[r];if(e[r]=this.clone(h),l){let c=e[r].metas.map(S=>S.phx_ref),f=l.metas.filter(S=>c.indexOf(S.phx_ref)<0);e[r].metas.unshift(...f)}i(r,l,h)}),this.map(n,(r,h)=>{let l=e[r];if(!l)return;let c=h.metas.map(f=>f.phx_ref);l.metas=l.metas.filter(f=>c.indexOf(f.phx_ref)<0),s(r,l,h),l.metas.length===0&&delete e[r]}),e}static list(e,t){return t||(t=function(i,s){return s}),this.map(e,(i,s)=>t(i,s))}static map(e,t){return Object.getOwnPropertyNames(e).map(i=>t(i,e[i]))}static clone(e){return JSON.parse(JSON.stringify(e))}};var y={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(a,e){if(a.payload.constructor===ArrayBuffer)return e(this.binaryEncode(a));{let t=[a.join_ref,a.ref,a.topic,a.event,a.payload];return e(JSON.stringify(t))}},decode(a,e){if(a.constructor===ArrayBuffer)return e(this.binaryDecode(a));{let[t,i,s,o,n]=JSON.parse(a);return e({join_ref:t,ref:i,topic:s,event:o,payload:n})}},binaryEncode(a){let{join_ref:e,ref:t,event:i,topic:s,payload:o}=a,n=this.META_LENGTH+e.length+t.length+s.length+i.length,r=new ArrayBuffer(this.HEADER_LENGTH+n),h=new DataView(r),l=0;h.setUint8(l++,this.KINDS.push),h.setUint8(l++,e.length),h.setUint8(l++,t.length),h.setUint8(l++,s.length),h.setUint8(l++,i.length),Array.from(e,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(t,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(s,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(i,f=>h.setUint8(l++,f.charCodeAt(0)));var c=new Uint8Array(r.byteLength+o.byteLength);return c.set(new Uint8Array(r),0),c.set(new Uint8Array(o),r.byteLength),c.buffer},binaryDecode(a){let e=new DataView(a),t=e.getUint8(0),i=new TextDecoder;switch(t){case this.KINDS.push:return this.decodePush(a,e,i);case this.KINDS.reply:return this.decodeReply(a,e,i);case this.KINDS.broadcast:return this.decodeBroadcast(a,e,i)}},decodePush(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),n=this.HEADER_LENGTH+this.META_LENGTH-1,r=t.decode(a.slice(n,n+i));n=n+i;let h=t.decode(a.slice(n,n+s));n=n+s;let l=t.decode(a.slice(n,n+o));n=n+o;let c=a.slice(n,a.byteLength);return{join_ref:r,ref:null,topic:h,event:l,payload:c}},decodeReply(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),n=e.getUint8(4),r=this.HEADER_LENGTH+this.META_LENGTH,h=t.decode(a.slice(r,r+i));r=r+i;let l=t.decode(a.slice(r,r+s));r=r+s;let c=t.decode(a.slice(r,r+o));r=r+o;let f=t.decode(a.slice(r,r+n));r=r+n;let S=a.slice(r,a.byteLength),x={status:f,response:S};return{join_ref:h,ref:l,topic:c,event:g.reply,payload:x}},decodeBroadcast(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=this.HEADER_LENGTH+2,n=t.decode(a.slice(o,o+i));o=o+i;let r=t.decode(a.slice(o,o+s));o=o+s;let h=a.slice(o,a.byteLength);return{join_ref:null,ref:null,topic:n,event:r,payload:h}}};var _=class{constructor(e,t={}){var s,o;this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.fallbackRef=null,this.timeout=t.timeout||B,this.transport=t.transport||d.WebSocket||m,this.conn=void 0,this.primaryPassedHealthCheck=!1,this.longPollFallbackMs=t.longPollFallbackMs,this.fallbackTimer=null,this.sessionStore=t.sessionStorage||d&&d.sessionStorage,this.establishedConnections=0,this.defaultEncoder=y.encode.bind(y),this.defaultDecoder=y.decode.bind(y),this.closeWasClean=!1,this.disconnecting=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.pageHidden=!1,this.encode=void 0,this.decode=void 0,this.transport!==m?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;R&&R.addEventListener&&(R.addEventListener("pagehide",n=>{this.conn&&(this.disconnect(),i=this.connectClock)}),R.addEventListener("pageshow",n=>{i===this.connectClock&&(i=null,this.connect())}),R.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?this.pageHidden=!0:(this.pageHidden=!1,this.isConnected()||this.teardown(()=>this.connect()))})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.autoSendHeartbeat=(s=t.autoSendHeartbeat)!=null?s:!0,this.heartbeatCallback=(o=t.heartbeatCallback)!=null?o:()=>{},this.rejoinAfterMs=n=>t.rejoinAfterMs?t.rejoinAfterMs(n):[1e3,2e3,5e3][n-1]||1e4,this.reconnectAfterMs=n=>t.reconnectAfterMs?t.reconnectAfterMs(n):[10,50,100,150,200,250,500,1e3,2e3][n-1]||5e3,this.logger=t.logger||null,!this.logger&&t.debug&&(this.logger=(n,r,h)=>{console.log(`${n}: ${r}`,h)}),this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=k(t.params||{}),this.endPoint=`${e}/${j.websocket}`,this.vsn=t.vsn||O,this.heartbeatTimeoutTimer=null,this.heartbeatTimer=null,this.heartbeatSentAt=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new b(()=>{if(this.pageHidden){this.log("Not reconnecting as page is hidden!"),this.teardown();return}this.teardown(()=>N(this,null,function*(){t.beforeReconnect&&(yield t.beforeReconnect()),this.connect()}))},this.reconnectAfterMs),this.authToken=t.authToken}getLongPollTransport(){return m}replaceTransport(e){this.connectClock++,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.conn&&(this.conn.close(),this.conn=null),this.transport=e}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=C.appendParams(C.appendParams(this.endPoint,this.params()),{vsn:this.vsn});return e.charAt(0)!=="/"?e:e.charAt(1)==="/"?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,i){this.connectClock++,this.disconnecting=!0,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.teardown(()=>{this.disconnecting=!1,e&&e()},t,i)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=k(e)),!(this.conn&&!this.disconnecting)&&(this.longPollFallbackMs&&this.transport!==m?this.connectWithFallback(m,this.longPollFallbackMs):this.transportConnect())}log(e,t,i){this.logger&&this.logger(e,t,i)}hasLogger(){return this.logger!==null}onOpen(e){let t=this.makeRef();return this.stateChangeCallbacks.open.push([t,e]),t}onClose(e){let t=this.makeRef();return this.stateChangeCallbacks.close.push([t,e]),t}onError(e){let t=this.makeRef();return this.stateChangeCallbacks.error.push([t,e]),t}onMessage(e){let t=this.makeRef();return this.stateChangeCallbacks.message.push([t,e]),t}onHeartbeat(e){this.heartbeatCallback=e}ping(e){if(!this.isConnected())return!1;let t=this.makeRef(),i=Date.now();this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:t});let s=this.onMessage(o=>{o.ref===t&&(this.off([s]),e(Date.now()-i))});return!0}transportConnect(){this.connectClock++,this.closeWasClean=!1;let e;this.authToken&&(e=["phoenix",`${A}${btoa(this.authToken).replace(/=/g,"")}`]),this.conn=new this.transport(this.endPointURL(),e),this.conn.binaryType=this.binaryType,this.conn.timeout=this.longpollerTimeout,this.conn.onopen=()=>this.onConnOpen(),this.conn.onerror=t=>this.onConnError(t),this.conn.onmessage=t=>this.onConnMessage(t),this.conn.onclose=t=>this.onConnClose(t)}getSession(e){return this.sessionStore&&this.sessionStore.getItem(e)}storeSession(e,t){this.sessionStore&&this.sessionStore.setItem(e,t)}connectWithFallback(e,t=2500){clearTimeout(this.fallbackTimer);let i=!1,s=!0,o,n,r=h=>{this.log("transport",`falling back to ${e.name}...`,h),this.off([o,n]),s=!1,this.replaceTransport(e),this.transportConnect()};if(this.getSession(`phx:fallback:${e.name}`))return r("memorized");this.fallbackTimer=setTimeout(r,t),n=this.onError(h=>{this.log("transport","error",h),s&&!i&&(clearTimeout(this.fallbackTimer),r(h))}),this.fallbackRef&&this.off([this.fallbackRef]),this.fallbackRef=this.onOpen(()=>{if(i=!0,!s)return this.primaryPassedHealthCheck||this.storeSession(`phx:fallback:${e.name}`,"true"),this.log("transport",`established ${e.name} fallback`);clearTimeout(this.fallbackTimer),this.fallbackTimer=setTimeout(r,t),this.ping(h=>{this.log("transport","connected to primary after",h),this.primaryPassedHealthCheck=!0,clearTimeout(this.fallbackTimer)})}),this.transportConnect()}clearHeartbeats(){clearTimeout(this.heartbeatTimer),clearTimeout(this.heartbeatTimeoutTimer)}onConnOpen(){this.hasLogger()&&this.log("transport",`connected to ${this.endPointURL()}`),this.closeWasClean=!1,this.disconnecting=!1,this.establishedConnections++,this.flushSendBuffer(),this.reconnectTimer.reset(),this.autoSendHeartbeat&&this.resetHeartbeat(),this.triggerStateCallbacks("open")}heartbeatTimeout(){if(this.pendingHeartbeatRef){this.pendingHeartbeatRef=null,this.heartbeatSentAt=null,this.hasLogger()&&this.log("transport","heartbeat timeout. Attempting to re-establish connection");try{this.heartbeatCallback("timeout")}catch(e){this.log("error","error in heartbeat callback",e)}this.triggerChanError(),this.closeWasClean=!1,this.teardown(()=>this.reconnectTimer.scheduleTimeout(),P,"heartbeat timeout")}}resetHeartbeat(){this.conn&&this.conn.skipHeartbeat||(this.pendingHeartbeatRef=null,this.clearHeartbeats(),this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}teardown(e,t,i){if(!this.conn)return e&&e();let s=this.connectClock;this.waitForBufferDone(()=>{s===this.connectClock&&(this.conn&&(t?this.conn.close(t,i||""):this.conn.close()),this.waitForSocketClosed(()=>{s===this.connectClock&&(this.conn&&(this.conn.onopen=function(){},this.conn.onerror=function(){},this.conn.onmessage=function(){},this.conn.onclose=function(){},this.conn=null),e&&e())}))})}waitForBufferDone(e,t=1){if(t===5||!this.conn||!this.conn.bufferedAmount){e();return}setTimeout(()=>{this.waitForBufferDone(e,t+1)},150*t)}waitForSocketClosed(e,t=1){if(t===5||!this.conn||this.conn.readyState===p.closed){e();return}setTimeout(()=>{this.waitForSocketClosed(e,t+1)},150*t)}onConnClose(e){this.conn&&(this.conn.onclose=()=>{}),this.hasLogger()&&this.log("transport","close",e),this.triggerChanError(),this.clearHeartbeats(),this.closeWasClean||this.reconnectTimer.scheduleTimeout(),this.triggerStateCallbacks("close",e)}onConnError(e){this.hasLogger()&&this.log("transport",e);let t=this.transport,i=this.establishedConnections;this.triggerStateCallbacks("error",e,t,i),(t===this.transport||i>0)&&this.triggerChanError()}triggerChanError(){this.channels.forEach(e=>{e.isErrored()||e.isLeaving()||e.isClosed()||e.trigger(g.error)})}connectionState(){switch(this.conn&&this.conn.readyState){case p.connecting:return"connecting";case p.open:return"open";case p.closing:return"closing";default:return"closed"}}isConnected(){return this.connectionState()==="open"}remove(e){this.off(e.stateChangeRefs),this.channels=this.channels.filter(t=>t!==e)}off(e){for(let t in this.stateChangeCallbacks)this.stateChangeCallbacks[t]=this.stateChangeCallbacks[t].filter(([i])=>e.indexOf(i)===-1)}channel(e,t={}){let i=new v(e,t,this);return this.channels.push(i),i}push(e){if(this.hasLogger()){let{topic:t,event:i,payload:s,ref:o,join_ref:n}=e;this.log("push",`${t} ${i} (${n}, ${o})`,s)}this.isConnected()?this.encode(e,t=>this.conn.send(t)):this.sendBuffer.push(()=>this.encode(e,t=>this.conn.send(t)))}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){if(!this.isConnected()){try{this.heartbeatCallback("disconnected")}catch(e){this.log("error","error in heartbeat callback",e)}return}if(this.pendingHeartbeatRef){this.heartbeatTimeout();return}this.pendingHeartbeatRef=this.makeRef(),this.heartbeatSentAt=Date.now(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef});try{this.heartbeatCallback("sent")}catch(e){this.log("error","error in heartbeat callback",e)}this.heartbeatTimeoutTimer=setTimeout(()=>this.heartbeatTimeout(),this.heartbeatIntervalMs)}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,t=>{let{topic:i,event:s,payload:o,ref:n,join_ref:r}=t;if(n&&n===this.pendingHeartbeatRef){let h=this.heartbeatSentAt?Date.now()-this.heartbeatSentAt:void 0;this.clearHeartbeats();try{this.heartbeatCallback(o.status==="ok"?"ok":"error",h)}catch(l){this.log("error","error in heartbeat callback",l)}this.pendingHeartbeatRef=null,this.heartbeatSentAt=null,this.autoSendHeartbeat&&(this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}this.hasLogger()&&this.log("receive",`${o.status||""} ${i} ${s} ${n&&"("+n+")"||""}`.trim(),o);for(let h=0;h<this.channels.length;h++){let l=this.channels[h];l.isMember(i,s,o,r)&&l.trigger(s,o,n,r)}this.triggerStateCallbacks("message",t)})}triggerStateCallbacks(e,...t){try{this.stateChangeCallbacks[e].forEach(([i,s])=>{try{s(...t)}catch(o){this.log("error",`error in ${e} callback`,o)}})}catch(i){this.log("error",`error triggering ${e} callbacks`,i)}}leaveOpenTopic(e){let t=this.channels.find(i=>i.topic===e&&(i.isJoined()||i.isJoining()));t&&(this.hasLogger()&&this.log("transport",`leaving duplicate topic "${e}"`),t.leave())}};return J(K);})();
|
|
1
|
+
"use strict";var Phoenix=(()=>{var L=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var I=(a,e)=>{for(var t in e)L(a,t,{get:e[t],enumerable:!0})},F=(a,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of U(e))!D.call(a,s)&&s!==t&&L(a,s,{get:()=>e[s],enumerable:!(i=M(e,s))||i.enumerable});return a};var J=a=>F(L({},"__esModule",{value:!0}),a);var N=(a,e,t)=>new Promise((i,s)=>{var o=h=>{try{r(t.next(h))}catch(l){s(l)}},n=h=>{try{r(t.throw(h))}catch(l){s(l)}},r=h=>h.done?i(h.value):Promise.resolve(h.value).then(o,n);r((t=t.apply(a,e)).next())});var K={};I(K,{Channel:()=>v,LongPoll:()=>m,Presence:()=>w,Push:()=>T,Serializer:()=>y,Socket:()=>_,Timer:()=>b});var k=a=>typeof a=="function"?a:function(){return a};var z=typeof self!="undefined"?self:null,R=typeof window!="undefined"?window:null,d=z||R||globalThis,O="2.0.0",P=1e4,B=1e3,p={connecting:0,open:1,closing:2,closed:3},u={closed:"closed",errored:"errored",joined:"joined",joining:"joining",leaving:"leaving"},g={close:"phx_close",error:"phx_error",join:"phx_join",reply:"phx_reply",leave:"phx_leave"},j={longpoll:"longpoll",websocket:"websocket"},$={complete:4},A="base64url.bearer.phx.";var T=class{constructor(e,t,i,s){this.channel=e,this.event=t,this.payload=i||function(){return{}},this.receivedResp=null,this.timeout=s,this.timeoutTimer=null,this.recHooks=[],this.sent=!1,this.ref=void 0}resend(e){this.timeout=e,this.reset(),this.send()}send(){this.hasReceived("timeout")||(this.startTimeout(),this.sent=!0,this.channel.socket.push({topic:this.channel.topic,event:this.event,payload:this.payload(),ref:this.ref,join_ref:this.channel.joinRef()}))}receive(e,t){return this.hasReceived(e)&&t(this.receivedResp.response),this.recHooks.push({status:e,callback:t}),this}reset(){this.cancelRefEvent(),this.ref=null,this.refEvent=null,this.receivedResp=null,this.sent=!1}destroy(){this.cancelRefEvent(),this.cancelTimeout()}matchReceive({status:e,response:t,_ref:i}){this.recHooks.filter(s=>s.status===e).forEach(s=>s.callback(t))}cancelRefEvent(){this.refEvent&&this.channel.off(this.refEvent)}cancelTimeout(){clearTimeout(this.timeoutTimer),this.timeoutTimer=null}startTimeout(){this.timeoutTimer&&this.cancelTimeout(),this.ref=this.channel.socket.makeRef(),this.refEvent=this.channel.replyEventName(this.ref),this.channel.on(this.refEvent,e=>{this.cancelRefEvent(),this.cancelTimeout(),this.receivedResp=e,this.matchReceive(e)}),this.timeoutTimer=setTimeout(()=>{this.trigger("timeout",{})},this.timeout)}hasReceived(e){return this.receivedResp&&this.receivedResp.status===e}trigger(e,t){this.channel.trigger(this.refEvent,{status:e,response:t})}};var b=class{constructor(e,t){this.callback=e,this.timerCalc=t,this.timer=void 0,this.tries=0}reset(){this.tries=0,clearTimeout(this.timer)}scheduleTimeout(){clearTimeout(this.timer),this.timer=setTimeout(()=>{this.tries=this.tries+1,this.callback()},this.timerCalc(this.tries+1))}};var v=class{constructor(e,t,i){this.state=u.closed,this.topic=e,this.params=k(t||{}),this.socket=i,this.bindings=[],this.bindingRef=0,this.timeout=this.socket.timeout,this.joinedOnce=!1,this.joinPush=new T(this,g.join,this.params,this.timeout),this.pushBuffer=[],this.stateChangeRefs=[],this.rejoinTimer=new b(()=>{this.socket.isConnected()&&this.rejoin()},this.socket.rejoinAfterMs),this.stateChangeRefs.push(this.socket.onError(()=>this.rejoinTimer.reset())),this.stateChangeRefs.push(this.socket.onOpen(()=>{this.rejoinTimer.reset(),this.isErrored()&&this.rejoin()})),this.joinPush.receive("ok",()=>{this.state=u.joined,this.rejoinTimer.reset(),this.pushBuffer.forEach(s=>s.send()),this.pushBuffer=[]}),this.joinPush.receive("error",s=>{this.state=u.errored,this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.onClose(()=>{this.rejoinTimer.reset(),this.socket.hasLogger()&&this.socket.log("channel",`close ${this.topic}`),this.state=u.closed,this.socket.remove(this)}),this.onError(s=>{this.socket.hasLogger()&&this.socket.log("channel",`error ${this.topic}`,s),this.isJoining()&&this.joinPush.reset(),this.state=u.errored,this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.joinPush.receive("timeout",()=>{this.socket.hasLogger()&&this.socket.log("channel",`timeout ${this.topic}`,this.joinPush.timeout),new T(this,g.leave,k({}),this.timeout).send(),this.state=u.errored,this.joinPush.reset(),this.socket.isConnected()&&this.rejoinTimer.scheduleTimeout()}),this.on(g.reply,(s,o)=>{this.trigger(this.replyEventName(o),s)})}join(e=this.timeout){if(this.joinedOnce)throw new Error("tried to join multiple times. 'join' can only be called a single time per channel instance");return this.timeout=e,this.joinedOnce=!0,this.rejoin(),this.joinPush}teardown(){this.pushBuffer.forEach(e=>e.destroy()),this.pushBuffer=[],this.rejoinTimer.reset(),this.joinPush.destroy(),this.state=u.closed,this.bindings={}}onClose(e){this.on(g.close,e)}onError(e){return this.on(g.error,t=>e(t))}on(e,t){let i=this.bindingRef++;return this.bindings.push({event:e,ref:i,callback:t}),i}off(e,t){this.bindings=this.bindings.filter(i=>!(i.event===e&&(typeof t=="undefined"||t===i.ref)))}canPush(){return this.socket.isConnected()&&this.isJoined()}push(e,t,i=this.timeout){if(t=t||{},!this.joinedOnce)throw new Error(`tried to push '${e}' to '${this.topic}' before joining. Use channel.join() before pushing events`);let s=new T(this,e,function(){return t},i);return this.canPush()?s.send():(s.startTimeout(),this.pushBuffer.push(s)),s}leave(e=this.timeout){this.rejoinTimer.reset(),this.joinPush.cancelTimeout(),this.state=u.leaving;let t=()=>{this.socket.hasLogger()&&this.socket.log("channel",`leave ${this.topic}`),this.trigger(g.close,"leave")},i=new T(this,g.leave,k({}),e);return i.receive("ok",()=>t()).receive("timeout",()=>t()),i.send(),this.canPush()||i.trigger("ok",{}),i}onMessage(e,t,i){return t}filterBindings(e,t,i){return!0}isMember(e,t,i,s){return this.topic!==e?!1:s&&s!==this.joinRef()?(this.socket.hasLogger()&&this.socket.log("channel","dropping outdated message",{topic:e,event:t,payload:i,joinRef:s}),!1):!0}joinRef(){return this.joinPush.ref}rejoin(e=this.timeout){this.isLeaving()||(this.socket.leaveOpenTopic(this.topic),this.state=u.joining,this.joinPush.resend(e))}trigger(e,t,i,s){let o=this.onMessage(e,t,i,s);if(t&&!o)throw new Error("channel onMessage callbacks must return the payload, modified or unmodified");let n=this.bindings.filter(r=>r.event===e&&this.filterBindings(r,t,i));for(let r=0;r<n.length;r++)n[r].callback(o,i,s||this.joinRef())}replyEventName(e){return`chan_reply_${e}`}isClosed(){return this.state===u.closed}isErrored(){return this.state===u.errored}isJoined(){return this.state===u.joined}isJoining(){return this.state===u.joining}isLeaving(){return this.state===u.leaving}};var C=class{static request(e,t,i,s,o,n,r){if(d.XDomainRequest){let h=new d.XDomainRequest;return this.xdomainRequest(h,e,t,s,o,n,r)}else if(d.XMLHttpRequest){let h=new d.XMLHttpRequest;return this.xhrRequest(h,e,t,i,s,o,n,r)}else{if(d.fetch&&d.AbortController)return this.fetchRequest(e,t,i,s,o,n,r);throw new Error("No suitable XMLHttpRequest implementation found")}}static fetchRequest(e,t,i,s,o,n,r){let h={method:e,headers:i,body:s},l=null;if(o){l=new AbortController;let c=setTimeout(()=>l.abort(),o);h.signal=l.signal}return d.fetch(t,h).then(c=>c.text()).then(c=>this.parseJSON(c)).then(c=>r&&r(c)).catch(c=>{c.name==="AbortError"&&n?n():r&&r(null)}),l}static xdomainRequest(e,t,i,s,o,n,r){return e.timeout=o,e.open(t,i),e.onload=()=>{let h=this.parseJSON(e.responseText);r&&r(h)},n&&(e.ontimeout=n),e.onprogress=()=>{},e.send(s),e}static xhrRequest(e,t,i,s,o,n,r,h){e.open(t,i,!0),e.timeout=n;for(let[l,c]of Object.entries(s))e.setRequestHeader(l,c);return e.onerror=()=>h&&h(null),e.onreadystatechange=()=>{if(e.readyState===$.complete&&h){let l=this.parseJSON(e.responseText);h(l)}},r&&(e.ontimeout=r),e.send(o),e}static parseJSON(e){if(!e||e==="")return null;try{return JSON.parse(e)}catch(t){return console&&console.log("failed to parse JSON response",e),null}}static serialize(e,t){let i=[];for(var s in e){if(!Object.prototype.hasOwnProperty.call(e,s))continue;let o=t?`${t}[${s}]`:s,n=e[s];typeof n=="object"?i.push(this.serialize(n,o)):i.push(encodeURIComponent(o)+"="+encodeURIComponent(n))}return i.join("&")}static appendParams(e,t){if(Object.keys(t).length===0)return e;let i=e.match(/\?/)?"&":"?";return`${e}${i}${this.serialize(t)}`}};var W=a=>{let e="",t=new Uint8Array(a),i=t.byteLength;for(let s=0;s<i;s++)e+=String.fromCharCode(t[s]);return btoa(e)},m=class{constructor(e,t){t&&t.length===2&&t[1].startsWith(A)&&(this.authToken=atob(t[1].slice(A.length))),this.endPoint=null,this.token=null,this.skipHeartbeat=!0,this.reqs=new Set,this.awaitingBatchAck=!1,this.currentBatch=null,this.currentBatchTimer=null,this.batchBuffer=[],this.onopen=function(){},this.onerror=function(){},this.onmessage=function(){},this.onclose=function(){},this.pollEndpoint=this.normalizeEndpoint(e),this.readyState=p.connecting,setTimeout(()=>this.poll(),0)}normalizeEndpoint(e){return e.replace("ws://","http://").replace("wss://","https://").replace(new RegExp("(.*)/"+j.websocket),"$1/"+j.longpoll)}endpointURL(){return C.appendParams(this.pollEndpoint,{token:this.token})}closeAndRetry(e,t,i){this.close(e,t,i),this.readyState=p.connecting}ontimeout(){this.onerror("timeout"),this.closeAndRetry(1005,"timeout",!1)}isActive(){return this.readyState===p.open||this.readyState===p.connecting}poll(){let e={Accept:"application/json"};this.authToken&&(e["X-Phoenix-AuthToken"]=this.authToken),this.ajax("GET",e,null,()=>this.ontimeout(),t=>{if(t){var{status:i,token:s,messages:o}=t;if(i===410&&this.token!==null){this.onerror(410),this.closeAndRetry(3410,"session_gone",!1);return}this.token=s}else i=0;switch(i){case 200:o.forEach(n=>{setTimeout(()=>this.onmessage({data:n}),0)}),this.poll();break;case 204:this.poll();break;case 410:this.readyState=p.open,this.onopen({}),this.poll();break;case 403:this.onerror(403),this.close(1008,"forbidden",!1);break;case 0:case 500:this.onerror(500),this.closeAndRetry(1011,"internal server error",500);break;default:throw new Error(`unhandled poll status ${i}`)}})}send(e){typeof e!="string"&&(e=W(e)),this.currentBatch?this.currentBatch.push(e):this.awaitingBatchAck?this.batchBuffer.push(e):(this.currentBatch=[e],this.currentBatchTimer=setTimeout(()=>{this.batchSend(this.currentBatch),this.currentBatch=null},0))}batchSend(e){this.awaitingBatchAck=!0,this.ajax("POST",{"Content-Type":"application/x-ndjson"},e.join(`
|
|
2
|
+
`),()=>this.onerror("timeout"),t=>{this.awaitingBatchAck=!1,!t||t.status!==200?(this.onerror(t&&t.status),this.closeAndRetry(1011,"internal server error",!1)):this.batchBuffer.length>0&&(this.batchSend(this.batchBuffer),this.batchBuffer=[])})}close(e,t,i){for(let o of this.reqs)o.abort();this.readyState=p.closed;let s=Object.assign({code:1e3,reason:void 0,wasClean:!0},{code:e,reason:t,wasClean:i});this.batchBuffer=[],clearTimeout(this.currentBatchTimer),this.currentBatchTimer=null,typeof CloseEvent!="undefined"?this.onclose(new CloseEvent("close",s)):this.onclose(s)}ajax(e,t,i,s,o){let n,r=()=>{this.reqs.delete(n),s()};n=C.request(e,this.endpointURL(),t,i,this.timeout,r,h=>{this.reqs.delete(n),this.isActive()&&o(h)}),this.reqs.add(n)}};var w=class a{constructor(e,t={}){let i=t.events||{state:"presence_state",diff:"presence_diff"};this.state={},this.pendingDiffs=[],this.channel=e,this.joinRef=null,this.caller={onJoin:function(){},onLeave:function(){},onSync:function(){}},this.channel.on(i.state,s=>{let{onJoin:o,onLeave:n,onSync:r}=this.caller;this.joinRef=this.channel.joinRef(),this.state=a.syncState(this.state,s,o,n),this.pendingDiffs.forEach(h=>{this.state=a.syncDiff(this.state,h,o,n)}),this.pendingDiffs=[],r()}),this.channel.on(i.diff,s=>{let{onJoin:o,onLeave:n,onSync:r}=this.caller;this.inPendingSyncState()?this.pendingDiffs.push(s):(this.state=a.syncDiff(this.state,s,o,n),r())})}onJoin(e){this.caller.onJoin=e}onLeave(e){this.caller.onLeave=e}onSync(e){this.caller.onSync=e}list(e){return a.list(this.state,e)}inPendingSyncState(){return!this.joinRef||this.joinRef!==this.channel.joinRef()}static syncState(e,t,i,s){let o=this.clone(e),n={},r={};return this.map(o,(h,l)=>{t[h]||(r[h]=l)}),this.map(t,(h,l)=>{let c=o[h];if(c){let f=l.metas.map(E=>E.phx_ref),S=c.metas.map(E=>E.phx_ref),x=l.metas.filter(E=>S.indexOf(E.phx_ref)<0),H=c.metas.filter(E=>f.indexOf(E.phx_ref)<0);x.length>0&&(n[h]=l,n[h].metas=x),H.length>0&&(r[h]=this.clone(c),r[h].metas=H)}else n[h]=l}),this.syncDiff(o,{joins:n,leaves:r},i,s)}static syncDiff(e,t,i,s){let{joins:o,leaves:n}=this.clone(t);return i||(i=function(){}),s||(s=function(){}),this.map(o,(r,h)=>{let l=e[r];if(e[r]=this.clone(h),l){let c=e[r].metas.map(S=>S.phx_ref),f=l.metas.filter(S=>c.indexOf(S.phx_ref)<0);e[r].metas.unshift(...f)}i(r,l,h)}),this.map(n,(r,h)=>{let l=e[r];if(!l)return;let c=h.metas.map(f=>f.phx_ref);l.metas=l.metas.filter(f=>c.indexOf(f.phx_ref)<0),s(r,l,h),l.metas.length===0&&delete e[r]}),e}static list(e,t){return t||(t=function(i,s){return s}),this.map(e,(i,s)=>t(i,s))}static map(e,t){return Object.getOwnPropertyNames(e).map(i=>t(i,e[i]))}static clone(e){return JSON.parse(JSON.stringify(e))}};var y={HEADER_LENGTH:1,META_LENGTH:4,KINDS:{push:0,reply:1,broadcast:2},encode(a,e){if(a.payload.constructor===ArrayBuffer)return e(this.binaryEncode(a));{let t=[a.join_ref,a.ref,a.topic,a.event,a.payload];return e(JSON.stringify(t))}},decode(a,e){if(a.constructor===ArrayBuffer)return e(this.binaryDecode(a));{let[t,i,s,o,n]=JSON.parse(a);return e({join_ref:t,ref:i,topic:s,event:o,payload:n})}},binaryEncode(a){let{join_ref:e,ref:t,event:i,topic:s,payload:o}=a,n=this.META_LENGTH+e.length+t.length+s.length+i.length,r=new ArrayBuffer(this.HEADER_LENGTH+n),h=new DataView(r),l=0;h.setUint8(l++,this.KINDS.push),h.setUint8(l++,e.length),h.setUint8(l++,t.length),h.setUint8(l++,s.length),h.setUint8(l++,i.length),Array.from(e,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(t,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(s,f=>h.setUint8(l++,f.charCodeAt(0))),Array.from(i,f=>h.setUint8(l++,f.charCodeAt(0)));var c=new Uint8Array(r.byteLength+o.byteLength);return c.set(new Uint8Array(r),0),c.set(new Uint8Array(o),r.byteLength),c.buffer},binaryDecode(a){let e=new DataView(a),t=e.getUint8(0),i=new TextDecoder;switch(t){case this.KINDS.push:return this.decodePush(a,e,i);case this.KINDS.reply:return this.decodeReply(a,e,i);case this.KINDS.broadcast:return this.decodeBroadcast(a,e,i)}},decodePush(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),n=this.HEADER_LENGTH+this.META_LENGTH-1,r=t.decode(a.slice(n,n+i));n=n+i;let h=t.decode(a.slice(n,n+s));n=n+s;let l=t.decode(a.slice(n,n+o));n=n+o;let c=a.slice(n,a.byteLength);return{join_ref:r,ref:null,topic:h,event:l,payload:c}},decodeReply(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=e.getUint8(3),n=e.getUint8(4),r=this.HEADER_LENGTH+this.META_LENGTH,h=t.decode(a.slice(r,r+i));r=r+i;let l=t.decode(a.slice(r,r+s));r=r+s;let c=t.decode(a.slice(r,r+o));r=r+o;let f=t.decode(a.slice(r,r+n));r=r+n;let S=a.slice(r,a.byteLength),x={status:f,response:S};return{join_ref:h,ref:l,topic:c,event:g.reply,payload:x}},decodeBroadcast(a,e,t){let i=e.getUint8(1),s=e.getUint8(2),o=this.HEADER_LENGTH+2,n=t.decode(a.slice(o,o+i));o=o+i;let r=t.decode(a.slice(o,o+s));o=o+s;let h=a.slice(o,a.byteLength);return{join_ref:null,ref:null,topic:n,event:r,payload:h}}};var _=class{constructor(e,t={}){var s,o;this.stateChangeCallbacks={open:[],close:[],error:[],message:[]},this.channels=[],this.sendBuffer=[],this.ref=0,this.fallbackRef=null,this.timeout=t.timeout||P,this.transport=t.transport||d.WebSocket||m,this.conn=void 0,this.primaryPassedHealthCheck=!1,this.longPollFallbackMs=t.longPollFallbackMs,this.fallbackTimer=null,this.sessionStore=t.sessionStorage||d&&d.sessionStorage,this.establishedConnections=0,this.defaultEncoder=y.encode.bind(y),this.defaultDecoder=y.decode.bind(y),this.closeWasClean=!1,this.disconnecting=!1,this.binaryType=t.binaryType||"arraybuffer",this.connectClock=1,this.pageHidden=!1,this.encode=void 0,this.decode=void 0,this.transport!==m?(this.encode=t.encode||this.defaultEncoder,this.decode=t.decode||this.defaultDecoder):(this.encode=this.defaultEncoder,this.decode=this.defaultDecoder);let i=null;R&&R.addEventListener&&(R.addEventListener("pagehide",n=>{this.conn&&(this.disconnect(),i=this.connectClock)}),R.addEventListener("pageshow",n=>{i===this.connectClock&&(i=null,this.connect())}),R.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"?this.pageHidden=!0:(this.pageHidden=!1,!this.isConnected()&&!this.closeWasClean&&this.teardown(()=>this.connect()))})),this.heartbeatIntervalMs=t.heartbeatIntervalMs||3e4,this.autoSendHeartbeat=(s=t.autoSendHeartbeat)!=null?s:!0,this.heartbeatCallback=(o=t.heartbeatCallback)!=null?o:()=>{},this.rejoinAfterMs=n=>t.rejoinAfterMs?t.rejoinAfterMs(n):[1e3,2e3,5e3][n-1]||1e4,this.reconnectAfterMs=n=>t.reconnectAfterMs?t.reconnectAfterMs(n):[10,50,100,150,200,250,500,1e3,2e3][n-1]||5e3,this.logger=t.logger||null,!this.logger&&t.debug&&(this.logger=(n,r,h)=>{console.log(`${n}: ${r}`,h)}),this.longpollerTimeout=t.longpollerTimeout||2e4,this.params=k(t.params||{}),this.endPoint=`${e}/${j.websocket}`,this.vsn=t.vsn||O,this.heartbeatTimeoutTimer=null,this.heartbeatTimer=null,this.heartbeatSentAt=null,this.pendingHeartbeatRef=null,this.reconnectTimer=new b(()=>{if(this.pageHidden){this.log("Not reconnecting as page is hidden!"),this.teardown();return}this.teardown(()=>N(this,null,function*(){t.beforeReconnect&&(yield t.beforeReconnect()),this.connect()}))},this.reconnectAfterMs),this.authToken=t.authToken}getLongPollTransport(){return m}replaceTransport(e){this.connectClock++,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.conn&&(this.conn.close(),this.conn=null),this.transport=e}protocol(){return location.protocol.match(/^https/)?"wss":"ws"}endPointURL(){let e=C.appendParams(C.appendParams(this.endPoint,this.params()),{vsn:this.vsn});return e.charAt(0)!=="/"?e:e.charAt(1)==="/"?`${this.protocol()}:${e}`:`${this.protocol()}://${location.host}${e}`}disconnect(e,t,i){this.connectClock++,this.disconnecting=!0,this.closeWasClean=!0,clearTimeout(this.fallbackTimer),this.reconnectTimer.reset(),this.teardown(()=>{this.disconnecting=!1,e&&e()},t,i)}connect(e){e&&(console&&console.log("passing params to connect is deprecated. Instead pass :params to the Socket constructor"),this.params=k(e)),!(this.conn&&!this.disconnecting)&&(this.longPollFallbackMs&&this.transport!==m?this.connectWithFallback(m,this.longPollFallbackMs):this.transportConnect())}log(e,t,i){this.logger&&this.logger(e,t,i)}hasLogger(){return this.logger!==null}onOpen(e){let t=this.makeRef();return this.stateChangeCallbacks.open.push([t,e]),t}onClose(e){let t=this.makeRef();return this.stateChangeCallbacks.close.push([t,e]),t}onError(e){let t=this.makeRef();return this.stateChangeCallbacks.error.push([t,e]),t}onMessage(e){let t=this.makeRef();return this.stateChangeCallbacks.message.push([t,e]),t}onHeartbeat(e){this.heartbeatCallback=e}ping(e){if(!this.isConnected())return!1;let t=this.makeRef(),i=Date.now();this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:t});let s=this.onMessage(o=>{o.ref===t&&(this.off([s]),e(Date.now()-i))});return!0}transportName(e){switch(e){case m:return"LongPoll";default:return e.name}}transportConnect(){this.connectClock++,this.closeWasClean=!1;let e;this.authToken&&(e=["phoenix",`${A}${btoa(this.authToken).replace(/=/g,"")}`]),this.conn=new this.transport(this.endPointURL(),e),this.conn.binaryType=this.binaryType,this.conn.timeout=this.longpollerTimeout,this.conn.onopen=()=>this.onConnOpen(),this.conn.onerror=t=>this.onConnError(t),this.conn.onmessage=t=>this.onConnMessage(t),this.conn.onclose=t=>this.onConnClose(t)}getSession(e){return this.sessionStore&&this.sessionStore.getItem(e)}storeSession(e,t){this.sessionStore&&this.sessionStore.setItem(e,t)}connectWithFallback(e,t=2500){clearTimeout(this.fallbackTimer);let i=!1,s=!0,o,n,r=this.transportName(e),h=l=>{this.log("transport",`falling back to ${r}...`,l),this.off([o,n]),s=!1,this.replaceTransport(e),this.transportConnect()};if(this.getSession(`phx:fallback:${r}`))return h("memorized");this.fallbackTimer=setTimeout(h,t),n=this.onError(l=>{this.log("transport","error",l),s&&!i&&(clearTimeout(this.fallbackTimer),h(l))}),this.fallbackRef&&this.off([this.fallbackRef]),this.fallbackRef=this.onOpen(()=>{if(i=!0,!s){let l=this.transportName(e);return this.primaryPassedHealthCheck||this.storeSession(`phx:fallback:${l}`,"true"),this.log("transport",`established ${l} fallback`)}clearTimeout(this.fallbackTimer),this.fallbackTimer=setTimeout(h,t),this.ping(l=>{this.log("transport","connected to primary after",l),this.primaryPassedHealthCheck=!0,clearTimeout(this.fallbackTimer)})}),this.transportConnect()}clearHeartbeats(){clearTimeout(this.heartbeatTimer),clearTimeout(this.heartbeatTimeoutTimer)}onConnOpen(){this.hasLogger()&&this.log("transport",`connected to ${this.endPointURL()}`),this.closeWasClean=!1,this.disconnecting=!1,this.establishedConnections++,this.flushSendBuffer(),this.reconnectTimer.reset(),this.autoSendHeartbeat&&this.resetHeartbeat(),this.triggerStateCallbacks("open")}heartbeatTimeout(){if(this.pendingHeartbeatRef){this.pendingHeartbeatRef=null,this.heartbeatSentAt=null,this.hasLogger()&&this.log("transport","heartbeat timeout. Attempting to re-establish connection");try{this.heartbeatCallback("timeout")}catch(e){this.log("error","error in heartbeat callback",e)}this.triggerChanError(),this.closeWasClean=!1,this.teardown(()=>this.reconnectTimer.scheduleTimeout(),B,"heartbeat timeout")}}resetHeartbeat(){this.conn&&this.conn.skipHeartbeat||(this.pendingHeartbeatRef=null,this.clearHeartbeats(),this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}teardown(e,t,i){if(!this.conn)return e&&e();let s=this.connectClock;this.waitForBufferDone(()=>{s===this.connectClock&&(this.conn&&(t?this.conn.close(t,i||""):this.conn.close()),this.waitForSocketClosed(()=>{s===this.connectClock&&(this.conn&&(this.conn.onopen=function(){},this.conn.onerror=function(){},this.conn.onmessage=function(){},this.conn.onclose=function(){},this.conn=null),e&&e())}))})}waitForBufferDone(e,t=1){if(t===5||!this.conn||!this.conn.bufferedAmount){e();return}setTimeout(()=>{this.waitForBufferDone(e,t+1)},150*t)}waitForSocketClosed(e,t=1){if(t===5||!this.conn||this.conn.readyState===p.closed){e();return}setTimeout(()=>{this.waitForSocketClosed(e,t+1)},150*t)}onConnClose(e){this.conn&&(this.conn.onclose=()=>{}),this.hasLogger()&&this.log("transport","close",e),this.triggerChanError(),this.clearHeartbeats(),this.closeWasClean||this.reconnectTimer.scheduleTimeout(),this.triggerStateCallbacks("close",e)}onConnError(e){this.hasLogger()&&this.log("transport",e);let t=this.transport,i=this.establishedConnections;this.triggerStateCallbacks("error",e,t,i),(t===this.transport||i>0)&&this.triggerChanError()}triggerChanError(){this.channels.forEach(e=>{e.isErrored()||e.isLeaving()||e.isClosed()||e.trigger(g.error)})}connectionState(){switch(this.conn&&this.conn.readyState){case p.connecting:return"connecting";case p.open:return"open";case p.closing:return"closing";default:return"closed"}}isConnected(){return this.connectionState()==="open"}remove(e){this.off(e.stateChangeRefs),this.channels=this.channels.filter(t=>t!==e)}off(e){for(let t in this.stateChangeCallbacks)this.stateChangeCallbacks[t]=this.stateChangeCallbacks[t].filter(([i])=>e.indexOf(i)===-1)}channel(e,t={}){let i=new v(e,t,this);return this.channels.push(i),i}push(e){if(this.hasLogger()){let{topic:t,event:i,payload:s,ref:o,join_ref:n}=e;this.log("push",`${t} ${i} (${n}, ${o})`,s)}this.isConnected()?this.encode(e,t=>this.conn.send(t)):this.sendBuffer.push(()=>this.encode(e,t=>this.conn.send(t)))}makeRef(){let e=this.ref+1;return e===this.ref?this.ref=0:this.ref=e,this.ref.toString()}sendHeartbeat(){if(!this.isConnected()){try{this.heartbeatCallback("disconnected")}catch(e){this.log("error","error in heartbeat callback",e)}return}if(this.pendingHeartbeatRef){this.heartbeatTimeout();return}this.pendingHeartbeatRef=this.makeRef(),this.heartbeatSentAt=Date.now(),this.push({topic:"phoenix",event:"heartbeat",payload:{},ref:this.pendingHeartbeatRef});try{this.heartbeatCallback("sent")}catch(e){this.log("error","error in heartbeat callback",e)}this.heartbeatTimeoutTimer=setTimeout(()=>this.heartbeatTimeout(),this.heartbeatIntervalMs)}flushSendBuffer(){this.isConnected()&&this.sendBuffer.length>0&&(this.sendBuffer.forEach(e=>e()),this.sendBuffer=[])}onConnMessage(e){this.decode(e.data,t=>{let{topic:i,event:s,payload:o,ref:n,join_ref:r}=t;if(n&&n===this.pendingHeartbeatRef){let h=this.heartbeatSentAt?Date.now()-this.heartbeatSentAt:void 0;this.clearHeartbeats();try{this.heartbeatCallback(o.status==="ok"?"ok":"error",h)}catch(l){this.log("error","error in heartbeat callback",l)}this.pendingHeartbeatRef=null,this.heartbeatSentAt=null,this.autoSendHeartbeat&&(this.heartbeatTimer=setTimeout(()=>this.sendHeartbeat(),this.heartbeatIntervalMs))}this.hasLogger()&&this.log("receive",`${o.status||""} ${i} ${s} ${n&&"("+n+")"||""}`.trim(),o);for(let h=0;h<this.channels.length;h++){let l=this.channels[h];l.isMember(i,s,o,r)&&l.trigger(s,o,n,r)}this.triggerStateCallbacks("message",t)})}triggerStateCallbacks(e,...t){try{this.stateChangeCallbacks[e].forEach(([i,s])=>{try{s(...t)}catch(o){this.log("error",`error in ${e} callback`,o)}})}catch(i){this.log("error",`error triggering ${e} callbacks`,i)}}leaveOpenTopic(e){let t=this.channels.find(i=>i.topic===e&&(i.isJoined()||i.isJoining()));t&&(this.hasLogger()&&this.log("transport",`leaving duplicate topic "${e}"`),t.leave())}};return J(K);})();
|
package/priv/static/phoenix.mjs
CHANGED
|
@@ -1177,7 +1177,7 @@ var Socket = class {
|
|
|
1177
1177
|
this.pageHidden = true;
|
|
1178
1178
|
} else {
|
|
1179
1179
|
this.pageHidden = false;
|
|
1180
|
-
if (!this.isConnected()) {
|
|
1180
|
+
if (!this.isConnected() && !this.closeWasClean) {
|
|
1181
1181
|
this.teardown(() => this.connect());
|
|
1182
1182
|
}
|
|
1183
1183
|
}
|
|
@@ -1406,6 +1406,19 @@ var Socket = class {
|
|
|
1406
1406
|
});
|
|
1407
1407
|
return true;
|
|
1408
1408
|
}
|
|
1409
|
+
/**
|
|
1410
|
+
* @private
|
|
1411
|
+
*
|
|
1412
|
+
* @param {Function}
|
|
1413
|
+
*/
|
|
1414
|
+
transportName(transport) {
|
|
1415
|
+
switch (transport) {
|
|
1416
|
+
case LongPoll:
|
|
1417
|
+
return "LongPoll";
|
|
1418
|
+
default:
|
|
1419
|
+
return transport.name;
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1409
1422
|
/**
|
|
1410
1423
|
* @private
|
|
1411
1424
|
*/
|
|
@@ -1435,14 +1448,15 @@ var Socket = class {
|
|
|
1435
1448
|
let established = false;
|
|
1436
1449
|
let primaryTransport = true;
|
|
1437
1450
|
let openRef, errorRef;
|
|
1451
|
+
let fallbackTransportName = this.transportName(fallbackTransport);
|
|
1438
1452
|
let fallback = (reason) => {
|
|
1439
|
-
this.log("transport", `falling back to ${
|
|
1453
|
+
this.log("transport", `falling back to ${fallbackTransportName}...`, reason);
|
|
1440
1454
|
this.off([openRef, errorRef]);
|
|
1441
1455
|
primaryTransport = false;
|
|
1442
1456
|
this.replaceTransport(fallbackTransport);
|
|
1443
1457
|
this.transportConnect();
|
|
1444
1458
|
};
|
|
1445
|
-
if (this.getSession(`phx:fallback:${
|
|
1459
|
+
if (this.getSession(`phx:fallback:${fallbackTransportName}`)) {
|
|
1446
1460
|
return fallback("memorized");
|
|
1447
1461
|
}
|
|
1448
1462
|
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
|
|
@@ -1459,10 +1473,11 @@ var Socket = class {
|
|
|
1459
1473
|
this.fallbackRef = this.onOpen(() => {
|
|
1460
1474
|
established = true;
|
|
1461
1475
|
if (!primaryTransport) {
|
|
1476
|
+
let fallbackTransportName2 = this.transportName(fallbackTransport);
|
|
1462
1477
|
if (!this.primaryPassedHealthCheck) {
|
|
1463
|
-
this.storeSession(`phx:fallback:${
|
|
1478
|
+
this.storeSession(`phx:fallback:${fallbackTransportName2}`, "true");
|
|
1464
1479
|
}
|
|
1465
|
-
return this.log("transport", `established ${
|
|
1480
|
+
return this.log("transport", `established ${fallbackTransportName2} fallback`);
|
|
1466
1481
|
}
|
|
1467
1482
|
clearTimeout(this.fallbackTimer);
|
|
1468
1483
|
this.fallbackTimer = setTimeout(fallback, fallbackThreshold);
|