@sphoro/bugcatch-web-sdk 0.14.1 → 0.14.2
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/dist/bugcatch.es.js +1 -1
- package/dist/bugcatch.umd.js +1 -1
- package/package.json +1 -1
package/dist/bugcatch.es.js
CHANGED
package/dist/bugcatch.umd.js
CHANGED
|
@@ -992,5 +992,5 @@ button.primary .spinner { border-color: rgba(255,255,255,.4); border-top-color:
|
|
|
992
992
|
<a class="file" href="${n}" target="_blank" rel="noopener noreferrer" download>
|
|
993
993
|
<span class="nm">${e}</span>
|
|
994
994
|
${t.size?`<span class="sz">${x(Me(t.size))}</span>`:""}
|
|
995
|
-
</a>`}function ta(t){return t.scrollHeight-t.scrollTop-t.clientHeight<40}function yt(t){t.scrollTop=t.scrollHeight}function wt(t){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[t]||String(t||"").toLowerCase()}function et(t){const e=new Date(t).getTime();if(!Number.isFinite(e))return"";const n=Math.floor((Date.now()-e)/864e5);if(n<=0)return"today";if(n===1)return"yesterday";if(n<30)return`${n} days ago`;const o=Math.floor(n/30);return o===1?"a month ago":`${o} months ago`}function x(t){return String(t).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}const an=8e3;function na(t=an){const e=window.AudioContext||window.webkitAudioContext;try{return new e({sampleRate:t})}catch{return new e}}async function oa(t){if(t.state==="suspended")try{await t.resume()}catch{}}function aa(t,e,n){const o=e/n,i=new Float32Array(Math.floor(t.length/o));for(let r=0;r<i.length;r++){const s=Math.floor(r*o),l=Math.min(Math.floor((r+1)*o),t.length);let u=0;for(let g=s;g<l;g++)u+=t[g];i[r]=l>s?u/(l-s):0}return i}const ra=132,rn=32635;function ia(t){const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++){const o=Math.max(-1,Math.min(1,t[n]));let i=Math.round(o*32767);const r=i<0?128:0;r&&(i=-i),i>rn&&(i=rn),i+=ra;let s=7;for(let u=16384;!(i&u)&&s>0;s--,u>>=1);const l=i>>s+3&15;e[n]=~(r|s<<4|l)&255}return e}const sa=512;function ca(t,e,n,o=an){const i=t.createMediaStreamSource(e),r=t.createScriptProcessor(sa,1,1);r.onaudioprocess=l=>{const u=l.inputBuffer.getChannelData(0),g=t.sampleRate===o?u:aa(u,t.sampleRate,o);n(ia(g))},i.connect(r);const s=t.createGain();return s.gain.value=0,r.connect(s),s.connect(t.destination),{stop(){r.onaudioprocess=null;try{i.disconnect()}catch{}try{r.disconnect()}catch{}try{s.disconnect()}catch{}}}}const la="voiceai.realtime.v1",da=[{urls:"stun:stun.l.google.com:19302"}];function vt(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function xt(){var t;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((t=navigator.mediaDevices)!=null&&t.getUserMedia)}async function sn({realtimeUrl:t,stream:e,ringsUntil:n,onState:o,onAudioBlocked:i,onMicrophone:r}){const s=(m,w)=>{try{o==null||o(m,w)}catch{}},l=m=>{try{i==null||i(m)}catch{}},u=m=>{try{r==null||r(m)}catch{}};if(!xt()){const m=new Error("[BugCatch] this browser cannot make live calls.");throw s("failed",{reason:"unsupported"}),m}let g=e;if(!g)try{g=await vt()}catch(m){throw s("failed",{reason:"microphone",error:String((m==null?void 0:m.name)||m)}),m}let y;try{y=await ua(t)}catch(m){throw ln(g),s("failed",{reason:"connect"}),m}let p=null,b=null,h=!1,k=null,A=null,ie=null,S=!1,E=null,T=null,L=!1;const X=[];let q=!1,Q=!1,D=!1,$=null,se=null,ne=0;const De=2e3,xe=5e3,ot=3e4,ke=4,N=(m,w)=>{if(!h){h=!0,k&&(clearTimeout(k),k=null),ce(),T==null||T(),T=null,at(),E==null||E(),E=null;try{p==null||p.close()}catch{}ln(g),b&&(b.srcObject=null,b.remove(),b=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}s(m,w)}},oe=m=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(m))},Le=async()=>{if(L||ie||h||!A||!A.audio&&!A.transcript)return;L=!0;const m=A.encoding||"mulaw";if(m!=="mulaw"){cn(`this call is kept as ${m}, which this SDK cannot produce.`);return}const w=Number(A.sample_rate)||8e3;try{const I=na(w);if(await oa(I),h){try{I.close()}catch{}return}const K=ca(I,g,P=>{y.readyState===WebSocket.OPEN&&y.send(P)},w);ie={context:I,tap:K}}catch(I){cn(`could not send the copy this call is keeping: ${String((I==null?void 0:I.message)||I)}`)}};function at(){if(L=!1,!ie)return;const{context:m,tap:w}=ie;ie=null;try{w.stop()}catch{}try{m.close()}catch{}}function Ne(){var w;if(!b||h)return;let m;try{m=(w=b.play)==null?void 0:w.call(b)}catch{Be();return}if(!m||typeof m.then!="function"){ge();return}m.then(ge,Be)}function ge(){E==null||E(),E=null,S&&(S=!1,l(!1))}function Be(){h||(S||(S=!0,l(!0)),kt())}function kt(){if(E||typeof window>"u"||typeof window.addEventListener!="function")return;const m=()=>Ne(),w=["pointerdown","keydown","touchstart"];for(const I of w)window.addEventListener(I,m,{capture:!0,passive:!0});E=()=>{for(const I of w)try{window.removeEventListener(I,m,{capture:!0})}catch{}}}const Ae=m=>{p=new RTCPeerConnection({iceServers:m!=null&&m.length?m:da});for(const w of g.getAudioTracks())p.addTrack(w,g);T=de(),p.onicecandidate=w=>{w.candidate&&oe({type:"signal",signal:{kind:"candidate",payload:w.candidate.toJSON()}})},p.ontrack=w=>{var K;const[I]=w.streams;I&&(b||(b=document.createElement("audio"),b.autoplay=!0,b.playsInline=!0,(K=b.setAttribute)==null||K.call(b,"playsinline",""),b.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(b)),b.srcObject=I,Ne())},p.onconnectionstatechange=Se,p.oniceconnectionstatechange=Se};function Se(){if(!p||h)return;const m=p.connectionState||p.iceConnectionState;if(m==="connected"||m==="completed"){Q=!0,ne=0,ce(),D=!1,s("connected");return}if(m==="disconnected"){if(!Q)return;Ue(De);return}if(m==="failed"){if(!Q){N("failed",{reason:"ice"});return}Ue(0)}}function Ue(m){h||(D||(D=!0,s("reconnecting"),se=setTimeout(()=>N("failed",{reason:"network"}),ot)),!$&&($=setTimeout(Re,m)))}function ce(){$&&(clearTimeout($),$=null),se&&(clearTimeout(se),se=null)}async function Re(){if($=null,h||!p)return;const m=p.connectionState||p.iceConnectionState;if(!(m==="connected"||m==="completed")){if(!q){oe({type:"signal",signal:{kind:"restart",payload:{}}}),$=setTimeout(Re,xe);return}ne>=ke||(ne+=1,await z(),$=setTimeout(Re,xe))}}async function z(){if(!(h||!p))try{const m=await p.createOffer({iceRestart:!0});await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{}}function de(){let w=null,I=!1;const K=P=>{if(w&&(clearTimeout(w),w=null),P){if(!I)return;I=!1,u(!0);return}I||(w=setTimeout(()=>{w=null,!h&&(I=!0,u(!1))},600))};for(const P of g.getAudioTracks())P.onmute=()=>K(!1),P.onunmute=()=>K(!0),P.onended=()=>{w&&(clearTimeout(w),w=null),!I&&(I=!0,u(!1))};return()=>{w&&(clearTimeout(w),w=null);for(const P of g.getAudioTracks())P.onmute=null,P.onunmute=null,P.onended=null}}const rt=async()=>{try{const m=await p.createOffer();await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{N("failed",{reason:"negotiation"})}},St=async m=>{try{await p.setRemoteDescription(new RTCSessionDescription(m));const w=await p.createAnswer();await p.setLocalDescription(w),oe({type:"signal",signal:{kind:"answer",payload:p.localDescription.toJSON()}}),await Qe()}catch{N("failed",{reason:"negotiation"})}},Qe=async()=>{for(;X.length;){const m=X.shift();try{await p.addIceCandidate(new RTCIceCandidate(m))}catch{}}};let Ce=Promise.resolve();y.onmessage=m=>{Ce=Ce.then(()=>Ct(m)).catch(()=>{})};const Ct=async m=>{var I,K,P,Ee,it;if(typeof m.data!="string")return;let w;try{w=JSON.parse(m.data)}catch{return}switch(w.type){case"session.created":{if(Ae((I=w.data)==null?void 0:I.ice_servers),A=((K=w.data)==null?void 0:K.capture)||null,(P=w.data)!=null&&P.peer_present){s("connecting"),Le();break}s("ringing"),je();break}case"peer.joined":{k&&(clearTimeout(k),k=null),s("connecting"),q=!!((Ee=w.data)!=null&&Ee.should_offer),q&&await rt(),Le();break}case"signal":{if(!p)break;const{kind:$e,payload:fe}=w.data||{};if($e==="offer")await St(fe);else if($e==="answer")try{await p.setRemoteDescription(new RTCSessionDescription(fe)),await Qe()}catch{N("failed",{reason:"negotiation"})}else if($e==="candidate")if(p.remoteDescription)try{await p.addIceCandidate(new RTCIceCandidate(fe))}catch{}else X.push(fe);else $e==="restart"&&q&&await z();break}case"peer.left":N("ended",{reason:"peer_left"});break;case"error":N("failed",{reason:"server",detail:(it=w.error)==null?void 0:it.detail});break;case"session.ended":N("ended",{reason:"server"});break}};y.onclose=()=>N("ended",{reason:"disconnected"}),y.onerror=()=>N("failed",{reason:"socket"});function je(){if(!n)return;const m=new Date(n).getTime()-Date.now();Number.isFinite(m)&&(k=setTimeout(()=>N("missed"),Math.max(0,m)))}return{hangUp(){oe({type:"session.end"}),N("ended",{reason:"hung_up"})},setMuted(m){for(const w of g.getAudioTracks())w.enabled=!m;return m},isMuted(){return g.getAudioTracks().every(m=>!m.enabled)}}}function ua(t){return new Promise((e,n)=>{let o;try{o=new WebSocket(t,la)}catch(i){n(i);return}o.onopen=()=>{o.onopen=null,o.onerror=null,e(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function cn(t){try{console.warn(`[BugCatch] ${t}`)}catch{}}function ln(t){var e;for(const n of((e=t==null?void 0:t.getTracks)==null?void 0:e.call(t))??[])try{n.stop()}catch{}}const tt={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};let dn=!1;if(typeof window<"u"&&window.addEventListener)for(const t of["pointerdown","keydown","touchstart"])window.addEventListener(t,()=>{dn=!0},{once:!0,capture:!0,passive:!0});function pa(){var t;try{return!!((t=navigator.userActivation)!=null&&t.hasBeenActive)}catch{return!1}}function ha(){if(!dn&&!pa())return()=>{};const t=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!t)return()=>{};let e;try{e=new t}catch{return()=>{}}let n=!1,o=null;const i=[],r=({at:u,seconds:g,hz:y})=>{const p=e.currentTime+u,b=e.createGain();b.connect(e.destination),b.gain.setValueAtTime(0,p),b.gain.linearRampToValueAtTime(tt.peak,p+.02),b.gain.setValueAtTime(tt.peak,p+g-.06),b.gain.linearRampToValueAtTime(0,p+g);for(const h of y){const k=e.createOscillator();k.type="sine",k.frequency.value=h,k.connect(b),k.start(p),k.stop(p+g+.02),i.push(k)}},s=()=>{if(!n)try{tt.bursts.forEach(r)}catch{}},l=()=>{n||(s(),o=setInterval(s,tt.cycleMs))};return e.state==="running"?l():e.resume().then(l).catch(()=>{}),()=>{n=!0,o&&clearInterval(o);for(const u of i)try{u.stop()}catch{}try{e.close()}catch{}}}function fa(t){const e=Date.parse(t||"");return Number.isNaN(e)?0:Math.max(0,Math.round((e-Date.now())/1e3))}const un=["flex:1","padding:9px 12px","border:0","border-radius:8px","font:600 13px/1.4 inherit","cursor:pointer"].join(";");function ga({call:t,accent:e="#5b6ef5",position:n="bottom-right",onAnswer:o,onDecline:i,onExpire:r}){if(typeof document>"u"||!document.body)return()=>{};const[s,l]=String(n).split("-"),u=document.createElement("div");u.setAttribute("role","alertdialog"),u.setAttribute("aria-live","assertive"),u.setAttribute("aria-label",`${t.from||"Support"} is calling about ${t.reference}`),u.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${l==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:14px","border-radius:12px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 18px 44px rgba(0,0,0,0.5)",`border:1px solid ${e}`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const g=document.createElement("div");g.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",g.textContent=`${t.from||"Support"} is calling`;const y=document.createElement("div");y.style.cssText="color:#a4abba;margin-bottom:10px",y.textContent=t.project?`About your report ${t.reference} · ${t.project}`:`About your report ${t.reference}`;const p=document.createElement("div");p.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px";const b=document.createElement("button");b.type="button",b.textContent="Answer",b.style.cssText=`${un};background:${e};color:#fff`;const h=document.createElement("button");h.type="button",h.textContent="Not now",h.style.cssText=`${un};background:#2b2f3a;color:#c8cedb`;const k=document.createElement("div");if(k.style.cssText="display:flex;gap:8px",k.append(b,h),u.append(g,y,p),t.recorded){const L=document.createElement("div");L.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px",L.textContent="This call will be recorded.",u.append(L)}u.append(k),document.body.appendChild(u);const A=ha();let ie=!1,S=null;const E=()=>{ie||(ie=!0,S&&clearInterval(S),A(),u.style.opacity="0",u.style.transform="translateY(8px)",setTimeout(()=>u.remove(),250))},T=()=>{const L=fa(t.ringsUntil);if(p.textContent=L?`Ringing — ${L}s`:"The call has stopped ringing.",!L){E();try{r==null||r()}catch{}}};return T(),S=setInterval(T,1e3),b.addEventListener("click",()=>{E();try{o==null||o()}catch{}}),h.addEventListener("click",()=>{E();try{i==null||i()}catch{}}),requestAnimationFrame(()=>{u.style.opacity="1",u.style.transform="translateY(0)"}),E}const pn={name:"@sphoro/bugcatch-web-sdk",version:"0.14.1"},nt={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:"#4F46E5",attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null};class hn{constructor(){Rn(this,B);this.config={...nt},this.started=!1,this.teardown=[],this.consoleBuffer=Pe(nt.consoleLimit),this.networkBuffer=Pe(nt.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map}init(e={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;if(this.config={...nt,...e},!this.config.apiKey)throw new Error("[BugCatch] apiKey is required.");if(!this.config.projectId)throw new Error("[BugCatch] projectId is required.");return this.consoleBuffer=Pe(this.config.consoleLimit),this.networkBuffer=Pe(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(Pn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(_n(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Fn(this.consoleBuffer)),this.config.widget&&this.teardown.push(Xo(this)),this.config.updates&&re()&&(this.startWatching(),queueMicrotask(()=>V(this,B,ye).call(this))),this.started=!0,this}startWatching(){if(this.stopWatching)return this;this.stopWatching=Mo({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){V(this,B,zn).call(this,n);return}if(n!=null&&n.callWithdrawn){V(this,B,lt).call(this,n.callWithdrawn.callId);return}const o=yo(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),V(this,B,ye).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>V(this,B,lt).call(this));const e=n=>{(n.key===Je||n.key===null)&&V(this,B,ye).call(this)};return window.addEventListener("storage",e),this.teardown.push(()=>window.removeEventListener("storage",e)),this}on(e,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(e)||new Set;return o.add(n),this.listeners.set(e,o),()=>this.off(e,n)}off(e,n){var o;return(o=this.listeners.get(e))==null||o.delete(n),this}emit(e,n){for(const o of this.listeners.get(e)||[])try{o(n)}catch(i){console.error("[BugCatch] an update listener threw:",i)}}unreadUpdates(){return qe()}markUpdateRead(e){return wo(e),V(this,B,ye).call(this),this}markReportRead(e){return vo(e),V(this,B,ye).call(this),this}markUpdatesRead(){return Ut(),V(this,B,ye).call(this),this}async verifyFix(e,{result:n,resolvedAt:o,note:i}){const r=n==="STILL_HAPPENING"?await V(this,B,ct).call(this,{}):{};return Do({apiBase:this.config.apiBase,bugId:e,result:n,resolvedAt:o,note:i,metadata:r.metadata,logs:r.logs})}myReport(e){return So({apiBase:this.config.apiBase,bugId:e})}replyToReport(e,{body:n,attachments:o}={}){return Vt({apiBase:this.config.apiBase,bugId:e,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const e={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?e:this.kinds!==void 0?this.kinds:(this.kinds=await Co({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}async startCall(e){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await V(this,B,jn).call(this,e)}finally{this.callStarting=!1}}startLiveCall(e){return this.startCall(e)}canCallTeam(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}endCall(){var e;return(e=this.call)==null||e.hangUp(),this.call=null,this}myReports(){return ko({apiBase:this.config.apiBase})}hasReports(){return!!re()}forgetReports(){var e;return(e=this.stopWatching)==null||e.call(this),this.stopWatching=null,this.endCall(),ve(),V(this,B,ye).call(this),this}identify(e){return this.config.user=e,this}async uploadAttachment(e,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:e,mime:n||(e==null?void 0:e.type),onProgress:o})}async report({title:e,description:n="",priority:o="MEDIUM",metadata:i={},attachments:r=[],references:s=[]}={}){if(!this.started)throw new Error("[BugCatch] call init() first.");if(!e||!e.trim())throw new Error("[BugCatch] a title is required.");const l=(r||[]).filter(b=>(b==null?void 0:b.storageKey)&&Fe(b.mime,_e)).map(b=>({type:b.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:b.storageKey,mime:Fe(b.mime,_e)}));let u=await V(this,B,ct).call(this,{title:e.trim(),description:n,priority:o,metadata:i,media:l,references:s});if(typeof this.config.beforeSend=="function"){const b=this.config.beforeSend(u);if(b===!1)return{cancelled:!0};b&&typeof b=="object"&&(u=b)}const g=he(this.config.projectId),y=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...g!=null&&g.token?{"X-BugCatch-Session":g.token}:{}},body:JSON.stringify(u)});if(y.status===401&&g&&ft(this.config.projectId),!y.ok){let b="";try{const h=await y.json();b=Array.isArray(h.message)?h.message.join(", "):h.message||""}catch{}throw new Error(`[BugCatch] report failed (HTTP ${y.status})${b?": "+b:""}`)}const p=await y.json();return p.watchToken&&(mt(p.watchToken),this.config.updates&&this.startWatching()),p}loginState(){var e;return po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(e=he(this.config.projectId))==null?void 0:e.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=Po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}signedInAs(){const e=he(this.config.projectId);return e?{email:e.email,name:e.name}:null}signIn(e,{name:n}={}){var o;return ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(e,n){var i;const o=await fo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,code:n});return(i=this.config.user)!=null&&i.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const e=he(this.config.projectId),n=await go({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:e==null?void 0:e.token});return e!=null&&e.email&&((o=this.config.user)==null?void 0:o.email)===e.email&&(this.config.user=null),this.emit("signout",{email:(e==null?void 0:e.email)||null}),n}knownIssues(){var e;return zo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(e=he(this.config.projectId))==null?void 0:e.token})}matchKnownIssues(e,{signal:n}={}){var o;return Oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:e||"",sessionToken:(o=he(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(e,{email:n,name:o}={}){var s,l;const i=he(this.config.projectId),r=await zt();return Ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:e,reporterEmail:n||((s=this.config.user)==null?void 0:s.email),reporterName:o||((l=this.config.user)==null?void 0:l.name),metadata:{...r,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:i==null?void 0:i.token})}snapshot(){return{console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:Ot()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(e=>{try{e()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,ye=function(){const e=qe();if(this.emit("unread",{count:e.length,updates:e}),!!this.config.updateToast){if(!this.notifier){if(!e.length)return;this.notifier=jo({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(e)}},ct=async function({title:e,description:n="",priority:o="MEDIUM",metadata:i={},media:r=[],references:s=[]}){var l,u;return{projectId:this.config.projectId,...e?{title:e}:{},description:n,priority:o,url:window.location.href,reporterEmail:(l=this.config.user)==null?void 0:l.email,reporterName:(u=this.config.user)==null?void 0:u.name,metadata:{...await zt(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...i,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...s.length?{references:s}:{}}},Qn=async function(){const e=he(this.config.projectId);let n;try{n=await Eo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:e==null?void 0:e.token,payload:await V(this,B,ct).call(this,{})})}catch(o){throw o.status===401&&e&&ft(this.config.projectId),o}return n.watchToken&&(mt(n.watchToken),this.config.updates&&this.startWatching()),n},jn=async function(e){if(!xt())throw new Error("[BugCatch] this browser cannot make live calls.");const n=await vt();let o,i=null;try{if(e)o=await $o({apiBase:this.config.apiBase,bugId:e});else if(i=await V(this,B,Qn).call(this),e=i.id,o=i.live_call,!(o!=null&&o.realtime_url)){const s=new Error(`[BugCatch] the report was filed, but the team could not be rung${i.call_error?`: ${i.call_error}`:"."}`);throw s.filed=i,s.reason=i.call_error||null,s}}catch(s){for(const l of n.getTracks())l.stop();throw s}const r=await sn({realtimeUrl:o.realtime_url,stream:n,ringsUntil:o.rings_until,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),s==="missed"&&To({apiBase:this.config.apiBase,bugId:e,callId:o.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,...l}),this.emit("call",{bugId:e,live:!0,state:s,...l})}});return this.call=r,Object.assign(r,{bugId:e,callId:o.call_id,live:!0,filed:i})},zn=function(e){var i;const n=e.incomingCall;if(!this.config.voice||!xt()||((i=this.ringing)==null?void 0:i.callId)===n.callId||this.call||this.callStarting)return;V(this,B,lt).call(this);const o=ga({call:n,accent:this.config.accent,position:this.config.widgetPosition,onAnswer:()=>{V(this,B,On).call(this,e.bugId,n)},onDecline:()=>{this.ringing=null,Pt({apiBase:this.config.apiBase,bugId:e.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:o},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:e.bugId,...n})}catch{}this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"ringing"})},lt=function(e){if(this.ringing&&!(e&&this.ringing.callId!==e)){try{this.ringing.dismiss()}catch{}this.ringing=null}},On=async function(e,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o;try{o=await vt()}catch(r){this.callStarting=!1,Pt({apiBase:this.config.apiBase,bugId:e,callId:n.callId}),this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r});return}let i;try{i=await Io({apiBase:this.config.apiBase,bugId:e,callId:n.callId})}catch(r){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"missed",error:r});return}try{const r=await sn({realtimeUrl:i.realtime_url,stream:o,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,incoming:!0,...l}),this.emit("call",{bugId:e,live:!0,incoming:!0,state:s,...l})}});this.call=r,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"answered"})}catch(r){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r})}finally{this.callStarting=!1}};const fn=new hn;return fn.Client=hn,fn});
|
|
995
|
+
</a>`}function ta(t){return t.scrollHeight-t.scrollTop-t.clientHeight<40}function yt(t){t.scrollTop=t.scrollHeight}function wt(t){return{OPEN:"Open",IN_PROGRESS:"In progress",RESOLVED:"Fixed",CLOSED:"Closed"}[t]||String(t||"").toLowerCase()}function et(t){const e=new Date(t).getTime();if(!Number.isFinite(e))return"";const n=Math.floor((Date.now()-e)/864e5);if(n<=0)return"today";if(n===1)return"yesterday";if(n<30)return`${n} days ago`;const o=Math.floor(n/30);return o===1?"a month ago":`${o} months ago`}function x(t){return String(t).replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e])}const an=8e3;function na(t=an){const e=window.AudioContext||window.webkitAudioContext;try{return new e({sampleRate:t})}catch{return new e}}async function oa(t){if(t.state==="suspended")try{await t.resume()}catch{}}function aa(t,e,n){const o=e/n,i=new Float32Array(Math.floor(t.length/o));for(let r=0;r<i.length;r++){const s=Math.floor(r*o),l=Math.min(Math.floor((r+1)*o),t.length);let u=0;for(let g=s;g<l;g++)u+=t[g];i[r]=l>s?u/(l-s):0}return i}const ra=132,rn=32635;function ia(t){const e=new Uint8Array(t.length);for(let n=0;n<t.length;n++){const o=Math.max(-1,Math.min(1,t[n]));let i=Math.round(o*32767);const r=i<0?128:0;r&&(i=-i),i>rn&&(i=rn),i+=ra;let s=7;for(let u=16384;!(i&u)&&s>0;s--,u>>=1);const l=i>>s+3&15;e[n]=~(r|s<<4|l)&255}return e}const sa=512;function ca(t,e,n,o=an){const i=t.createMediaStreamSource(e),r=t.createScriptProcessor(sa,1,1);r.onaudioprocess=l=>{const u=l.inputBuffer.getChannelData(0),g=t.sampleRate===o?u:aa(u,t.sampleRate,o);n(ia(g))},i.connect(r);const s=t.createGain();return s.gain.value=0,r.connect(s),s.connect(t.destination),{stop(){r.onaudioprocess=null;try{i.disconnect()}catch{}try{r.disconnect()}catch{}try{s.disconnect()}catch{}}}}const la="voiceai.realtime.v1",da=[{urls:"stun:stun.l.google.com:19302"}];function vt(){return navigator.mediaDevices.getUserMedia({audio:{echoCancellation:!0,noiseSuppression:!0,autoGainControl:!0,channelCount:1}})}function xt(){var t;return typeof window<"u"&&typeof window.RTCPeerConnection=="function"&&!!((t=navigator.mediaDevices)!=null&&t.getUserMedia)}async function sn({realtimeUrl:t,stream:e,ringsUntil:n,onState:o,onAudioBlocked:i,onMicrophone:r}){const s=(m,w)=>{try{o==null||o(m,w)}catch{}},l=m=>{try{i==null||i(m)}catch{}},u=m=>{try{r==null||r(m)}catch{}};if(!xt()){const m=new Error("[BugCatch] this browser cannot make live calls.");throw s("failed",{reason:"unsupported"}),m}let g=e;if(!g)try{g=await vt()}catch(m){throw s("failed",{reason:"microphone",error:String((m==null?void 0:m.name)||m)}),m}let y;try{y=await ua(t)}catch(m){throw ln(g),s("failed",{reason:"connect"}),m}let p=null,b=null,h=!1,k=null,A=null,ie=null,S=!1,E=null,T=null,L=!1;const X=[];let q=!1,Q=!1,D=!1,$=null,se=null,ne=0;const De=2e3,xe=5e3,ot=3e4,ke=4,N=(m,w)=>{if(!h){h=!0,k&&(clearTimeout(k),k=null),ce(),T==null||T(),T=null,at(),E==null||E(),E=null;try{p==null||p.close()}catch{}ln(g),b&&(b.srcObject=null,b.remove(),b=null);try{y.readyState===WebSocket.OPEN&&y.close(1e3,"call over")}catch{}s(m,w)}},oe=m=>{y.readyState===WebSocket.OPEN&&y.send(JSON.stringify(m))},Le=async()=>{if(L||ie||h||!A||!A.audio&&!A.transcript)return;L=!0;const m=A.encoding||"mulaw";if(m!=="mulaw"){cn(`this call is kept as ${m}, which this SDK cannot produce.`);return}const w=Number(A.sample_rate)||8e3;try{const I=na(w);if(await oa(I),h){try{I.close()}catch{}return}const K=ca(I,g,P=>{y.readyState===WebSocket.OPEN&&y.send(P)},w);ie={context:I,tap:K}}catch(I){cn(`could not send the copy this call is keeping: ${String((I==null?void 0:I.message)||I)}`)}};function at(){if(L=!1,!ie)return;const{context:m,tap:w}=ie;ie=null;try{w.stop()}catch{}try{m.close()}catch{}}function Ne(){var w;if(!b||h)return;let m;try{m=(w=b.play)==null?void 0:w.call(b)}catch{Be();return}if(!m||typeof m.then!="function"){ge();return}m.then(ge,Be)}function ge(){E==null||E(),E=null,S&&(S=!1,l(!1))}function Be(){h||(S||(S=!0,l(!0)),kt())}function kt(){if(E||typeof window>"u"||typeof window.addEventListener!="function")return;const m=()=>Ne(),w=["pointerdown","keydown","touchstart"];for(const I of w)window.addEventListener(I,m,{capture:!0,passive:!0});E=()=>{for(const I of w)try{window.removeEventListener(I,m,{capture:!0})}catch{}}}const Ae=m=>{p=new RTCPeerConnection({iceServers:m!=null&&m.length?m:da});for(const w of g.getAudioTracks())p.addTrack(w,g);T=de(),p.onicecandidate=w=>{w.candidate&&oe({type:"signal",signal:{kind:"candidate",payload:w.candidate.toJSON()}})},p.ontrack=w=>{var K;const[I]=w.streams;I&&(b||(b=document.createElement("audio"),b.autoplay=!0,b.playsInline=!0,(K=b.setAttribute)==null||K.call(b,"playsinline",""),b.style.cssText="position:fixed;width:0;height:0;opacity:0;pointer-events:none",document.body.appendChild(b)),b.srcObject=I,Ne())},p.onconnectionstatechange=Se,p.oniceconnectionstatechange=Se};function Se(){if(!p||h)return;const m=p.connectionState||p.iceConnectionState;if(m==="connected"||m==="completed"){Q=!0,ne=0,ce(),D=!1,s("connected");return}if(m==="disconnected"){if(!Q)return;Ue(De);return}if(m==="failed"){if(!Q){N("failed",{reason:"ice"});return}Ue(0)}}function Ue(m){h||(D||(D=!0,s("reconnecting"),se=setTimeout(()=>N("failed",{reason:"network"}),ot)),!$&&($=setTimeout(Re,m)))}function ce(){$&&(clearTimeout($),$=null),se&&(clearTimeout(se),se=null)}async function Re(){if($=null,h||!p)return;const m=p.connectionState||p.iceConnectionState;if(!(m==="connected"||m==="completed")){if(!q){oe({type:"signal",signal:{kind:"restart",payload:{}}}),$=setTimeout(Re,xe);return}ne>=ke||(ne+=1,await z(),$=setTimeout(Re,xe))}}async function z(){if(!(h||!p))try{const m=await p.createOffer({iceRestart:!0});await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{}}function de(){let w=null,I=!1;const K=P=>{if(w&&(clearTimeout(w),w=null),P){if(!I)return;I=!1,u(!0);return}I||(w=setTimeout(()=>{w=null,!h&&(I=!0,u(!1))},600))};for(const P of g.getAudioTracks())P.onmute=()=>K(!1),P.onunmute=()=>K(!0),P.onended=()=>{w&&(clearTimeout(w),w=null),!I&&(I=!0,u(!1))};return()=>{w&&(clearTimeout(w),w=null);for(const P of g.getAudioTracks())P.onmute=null,P.onunmute=null,P.onended=null}}const rt=async()=>{try{const m=await p.createOffer();await p.setLocalDescription(m),oe({type:"signal",signal:{kind:"offer",payload:p.localDescription.toJSON()}})}catch{N("failed",{reason:"negotiation"})}},St=async m=>{try{await p.setRemoteDescription(new RTCSessionDescription(m));const w=await p.createAnswer();await p.setLocalDescription(w),oe({type:"signal",signal:{kind:"answer",payload:p.localDescription.toJSON()}}),await Qe()}catch{N("failed",{reason:"negotiation"})}},Qe=async()=>{for(;X.length;){const m=X.shift();try{await p.addIceCandidate(new RTCIceCandidate(m))}catch{}}};let Ce=Promise.resolve();y.onmessage=m=>{Ce=Ce.then(()=>Ct(m)).catch(()=>{})};const Ct=async m=>{var I,K,P,Ee,it;if(typeof m.data!="string")return;let w;try{w=JSON.parse(m.data)}catch{return}switch(w.type){case"session.created":{if(Ae((I=w.data)==null?void 0:I.ice_servers),A=((K=w.data)==null?void 0:K.capture)||null,(P=w.data)!=null&&P.peer_present){s("connecting"),Le();break}s("ringing"),je();break}case"peer.joined":{k&&(clearTimeout(k),k=null),s("connecting"),q=!!((Ee=w.data)!=null&&Ee.should_offer),q&&await rt(),Le();break}case"signal":{if(!p)break;const{kind:$e,payload:fe}=w.data||{};if($e==="offer")await St(fe);else if($e==="answer")try{await p.setRemoteDescription(new RTCSessionDescription(fe)),await Qe()}catch{N("failed",{reason:"negotiation"})}else if($e==="candidate")if(p.remoteDescription)try{await p.addIceCandidate(new RTCIceCandidate(fe))}catch{}else X.push(fe);else $e==="restart"&&q&&await z();break}case"peer.left":N("ended",{reason:"peer_left"});break;case"error":N("failed",{reason:"server",detail:(it=w.error)==null?void 0:it.detail});break;case"session.ended":N("ended",{reason:"server"});break}};y.onclose=()=>N("ended",{reason:"disconnected"}),y.onerror=()=>N("failed",{reason:"socket"});function je(){if(!n)return;const m=new Date(n).getTime()-Date.now();Number.isFinite(m)&&(k=setTimeout(()=>N("missed"),Math.max(0,m)))}return{hangUp(){oe({type:"session.end"}),N("ended",{reason:"hung_up"})},setMuted(m){for(const w of g.getAudioTracks())w.enabled=!m;return m},isMuted(){return g.getAudioTracks().every(m=>!m.enabled)}}}function ua(t){return new Promise((e,n)=>{let o;try{o=new WebSocket(t,la)}catch(i){n(i);return}o.onopen=()=>{o.onopen=null,o.onerror=null,e(o)},o.onerror=()=>{o.onopen=null,o.onerror=null,n(new Error("[BugCatch] could not connect the call."))}})}function cn(t){try{console.warn(`[BugCatch] ${t}`)}catch{}}function ln(t){var e;for(const n of((e=t==null?void 0:t.getTracks)==null?void 0:e.call(t))??[])try{n.stop()}catch{}}const tt={cycleMs:3e3,peak:.045,bursts:[{at:0,seconds:.4,hz:[440,660]},{at:.55,seconds:.4,hz:[440,660]}]};let dn=!1;if(typeof window<"u"&&window.addEventListener)for(const t of["pointerdown","keydown","touchstart"])window.addEventListener(t,()=>{dn=!0},{once:!0,capture:!0,passive:!0});function pa(){var t;try{return!!((t=navigator.userActivation)!=null&&t.hasBeenActive)}catch{return!1}}function ha(){if(!dn&&!pa())return()=>{};const t=typeof window<"u"&&(window.AudioContext||window.webkitAudioContext);if(!t)return()=>{};let e;try{e=new t}catch{return()=>{}}let n=!1,o=null;const i=[],r=({at:u,seconds:g,hz:y})=>{const p=e.currentTime+u,b=e.createGain();b.connect(e.destination),b.gain.setValueAtTime(0,p),b.gain.linearRampToValueAtTime(tt.peak,p+.02),b.gain.setValueAtTime(tt.peak,p+g-.06),b.gain.linearRampToValueAtTime(0,p+g);for(const h of y){const k=e.createOscillator();k.type="sine",k.frequency.value=h,k.connect(b),k.start(p),k.stop(p+g+.02),i.push(k)}},s=()=>{if(!n)try{tt.bursts.forEach(r)}catch{}},l=()=>{n||(s(),o=setInterval(s,tt.cycleMs))};return e.state==="running"?l():e.resume().then(l).catch(()=>{}),()=>{n=!0,o&&clearInterval(o);for(const u of i)try{u.stop()}catch{}try{e.close()}catch{}}}function fa(t){const e=Date.parse(t||"");return Number.isNaN(e)?0:Math.max(0,Math.round((e-Date.now())/1e3))}const un=["flex:1","padding:9px 12px","border:0","border-radius:8px","font:600 13px/1.4 inherit","cursor:pointer"].join(";");function ga({call:t,accent:e="#5b6ef5",position:n="bottom-right",onAnswer:o,onDecline:i,onExpire:r}){if(typeof document>"u"||!document.body)return()=>{};const[s,l]=String(n).split("-"),u=document.createElement("div");u.setAttribute("role","alertdialog"),u.setAttribute("aria-live","assertive"),u.setAttribute("aria-label",`${t.from||"Support"} is calling about ${t.reference}`),u.style.cssText=["position:fixed",`${s==="top"?"top":"bottom"}:20px`,`${l==="left"?"left":"right"}:20px`,"z-index:2147483647","width:300px","max-width:calc(100vw - 40px)","padding:14px","border-radius:12px","background:#1b1e26","color:#eceef2",'font:13px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif',"box-shadow:0 18px 44px rgba(0,0,0,0.5)",`border:1px solid ${e}`,"opacity:0","transform:translateY(8px)","transition:opacity .2s ease,transform .2s ease"].join(";");const g=document.createElement("div");g.style.cssText="font-weight:600;font-size:14px;margin-bottom:2px",g.textContent=`${t.from||"Support"} is calling`;const y=document.createElement("div");y.style.cssText="color:#a4abba;margin-bottom:10px",y.textContent=t.project?`About your report ${t.reference} · ${t.project}`:`About your report ${t.reference}`;const p=document.createElement("div");p.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px";const b=document.createElement("button");b.type="button",b.textContent="Answer",b.style.cssText=`${un};background:${e};color:#fff`;const h=document.createElement("button");h.type="button",h.textContent="Not now",h.style.cssText=`${un};background:#2b2f3a;color:#c8cedb`;const k=document.createElement("div");if(k.style.cssText="display:flex;gap:8px",k.append(b,h),u.append(g,y,p),t.recorded){const L=document.createElement("div");L.style.cssText="color:#7d8598;font-size:12px;margin-bottom:10px",L.textContent="This call will be recorded.",u.append(L)}u.append(k),document.body.appendChild(u);const A=ha();let ie=!1,S=null;const E=()=>{ie||(ie=!0,S&&clearInterval(S),A(),u.style.opacity="0",u.style.transform="translateY(8px)",setTimeout(()=>u.remove(),250))},T=()=>{const L=fa(t.ringsUntil);if(p.textContent=L?`Ringing — ${L}s`:"The call has stopped ringing.",!L){E();try{r==null||r()}catch{}}};return T(),S=setInterval(T,1e3),b.addEventListener("click",()=>{E();try{o==null||o()}catch{}}),h.addEventListener("click",()=>{E();try{i==null||i()}catch{}}),requestAnimationFrame(()=>{u.style.opacity="1",u.style.transform="translateY(0)"}),E}const pn={name:"@sphoro/bugcatch-web-sdk",version:"0.14.2"},nt={apiBase:"http://localhost:3000",apiKey:null,projectId:null,consoleLimit:100,networkLimit:50,captureConsole:!0,captureNetwork:!0,captureErrors:!0,widget:!0,widgetPosition:"bottom-right",theme:"auto",accent:"#4F46E5",attachments:!0,maxAttachments:5,maxAttachmentBytes:25*1024*1024,maxRecordingMs:12e4,beforeSend:null,user:null,updates:!0,updateToast:!0,onUpdate:null,voice:!0,onCallState:null,onIncomingCall:null};class hn{constructor(){Rn(this,B);this.config={...nt},this.started=!1,this.teardown=[],this.consoleBuffer=Pe(nt.consoleLimit),this.networkBuffer=Pe(nt.networkLimit),this.stopWatching=null,this.notifier=null,this.call=null,this.callStarting=!1,this.ringing=null,this.listeners=new Map}init(e={}){if(this.started)return console.warn("[BugCatch] init() called twice — ignoring the second call."),this;if(this.config={...nt,...e},!this.config.apiKey)throw new Error("[BugCatch] apiKey is required.");if(!this.config.projectId)throw new Error("[BugCatch] projectId is required.");return this.consoleBuffer=Pe(this.config.consoleLimit),this.networkBuffer=Pe(this.config.networkLimit),this.config.captureConsole&&this.teardown.push(Pn(this.consoleBuffer)),this.config.captureNetwork&&this.teardown.push(_n(this.networkBuffer)),this.config.captureErrors&&this.teardown.push(Fn(this.consoleBuffer)),this.config.widget&&this.teardown.push(Xo(this)),this.config.updates&&re()&&(this.startWatching(),queueMicrotask(()=>V(this,B,ye).call(this))),this.started=!0,this}startWatching(){if(this.stopWatching)return this;this.stopWatching=Mo({apiBase:this.config.apiBase,onUpdate:n=>{if(n!=null&&n.incomingCall){V(this,B,zn).call(this,n);return}if(n!=null&&n.callWithdrawn){V(this,B,lt).call(this,n.callWithdrawn.callId);return}const o=yo(n);typeof this.config.onUpdate=="function"&&this.config.onUpdate(o),this.emit("update",o),V(this,B,ye).call(this)}}),this.teardown.push(()=>{var n;return(n=this.stopWatching)==null?void 0:n.call(this)}),this.teardown.push(()=>V(this,B,lt).call(this));const e=n=>{(n.key===Je||n.key===null)&&V(this,B,ye).call(this)};return window.addEventListener("storage",e),this.teardown.push(()=>window.removeEventListener("storage",e)),this}on(e,n){if(typeof n!="function")return()=>{};const o=this.listeners.get(e)||new Set;return o.add(n),this.listeners.set(e,o),()=>this.off(e,n)}off(e,n){var o;return(o=this.listeners.get(e))==null||o.delete(n),this}emit(e,n){for(const o of this.listeners.get(e)||[])try{o(n)}catch(i){console.error("[BugCatch] an update listener threw:",i)}}unreadUpdates(){return qe()}markUpdateRead(e){return wo(e),V(this,B,ye).call(this),this}markReportRead(e){return vo(e),V(this,B,ye).call(this),this}markUpdatesRead(){return Ut(),V(this,B,ye).call(this),this}async verifyFix(e,{result:n,resolvedAt:o,note:i}){const r=n==="STILL_HAPPENING"?await V(this,B,ct).call(this,{}):{};return Do({apiBase:this.config.apiBase,bugId:e,result:n,resolvedAt:o,note:i,metadata:r.metadata,logs:r.logs})}myReport(e){return So({apiBase:this.config.apiBase,bugId:e})}replyToReport(e,{body:n,attachments:o}={}){return Vt({apiBase:this.config.apiBase,bugId:e,body:n,attachments:o})}async canCallNow(){return!!await this.callKind()}async callKind(){return(await this.callKinds()).live?"live":null}async callKinds(){var n;const e={agent:!1,live:!1};return!this.config.voice||!((n=this.config.user)!=null&&n.email)?e:this.kinds!==void 0?this.kinds:(this.kinds=await Co({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.kinds)}canCall(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}async startCall(e){var n;if(!this.config.voice)throw new Error("[BugCatch] calling is switched off.");if(this.call||this.callStarting)throw new Error("[BugCatch] a call is already running.");this.callStarting=!0;try{if(!await this.callKind())throw new Error((n=this.config.user)!=null&&n.email?"[BugCatch] calling is not available on this project.":"[BugCatch] a call needs to know who is calling — call identify() with an email first.");return await V(this,B,jn).call(this,e)}finally{this.callStarting=!1}}startLiveCall(e){return this.startCall(e)}canCallTeam(e){return this.config.voice?Kt({apiBase:this.config.apiBase,bugId:e}):Promise.resolve(!1)}endCall(){var e;return(e=this.call)==null||e.hangUp(),this.call=null,this}myReports(){return ko({apiBase:this.config.apiBase})}hasReports(){return!!re()}forgetReports(){var e;return(e=this.stopWatching)==null||e.call(this),this.stopWatching=null,this.endCall(),ve(),V(this,B,ye).call(this),this}identify(e){return this.config.user=e,this}async uploadAttachment(e,n,o){if(!this.started)throw new Error("[BugCatch] call init() first.");return oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,blob:e,mime:n||(e==null?void 0:e.type),onProgress:o})}async report({title:e,description:n="",priority:o="MEDIUM",metadata:i={},attachments:r=[],references:s=[]}={}){if(!this.started)throw new Error("[BugCatch] call init() first.");if(!e||!e.trim())throw new Error("[BugCatch] a title is required.");const l=(r||[]).filter(b=>(b==null?void 0:b.storageKey)&&Fe(b.mime,_e)).map(b=>({type:b.type==="VIDEO"?"VIDEO":"SCREENSHOT",storageKey:b.storageKey,mime:Fe(b.mime,_e)}));let u=await V(this,B,ct).call(this,{title:e.trim(),description:n,priority:o,metadata:i,media:l,references:s});if(typeof this.config.beforeSend=="function"){const b=this.config.beforeSend(u);if(b===!1)return{cancelled:!0};b&&typeof b=="object"&&(u=b)}const g=he(this.config.projectId),y=await fetch(`${this.config.apiBase}/ingest/bugs`,{method:"POST",headers:{"Content-Type":"application/json","X-BugCatch-Key":this.config.apiKey,...g!=null&&g.token?{"X-BugCatch-Session":g.token}:{}},body:JSON.stringify(u)});if(y.status===401&&g&&ft(this.config.projectId),!y.ok){let b="";try{const h=await y.json();b=Array.isArray(h.message)?h.message.join(", "):h.message||""}catch{}throw new Error(`[BugCatch] report failed (HTTP ${y.status})${b?": "+b:""}`)}const p=await y.json();return p.watchToken&&(mt(p.watchToken),this.config.updates&&this.startWatching()),p}loginState(){var e;return po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:(e=he(this.config.projectId))==null?void 0:e.token})}referenceFields(){return this.refFields?this.refFields:(this.refFields=Po({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId}),this.refFields)}signedInAs(){const e=he(this.config.projectId);return e?{email:e.email,name:e.name}:null}signIn(e,{name:n}={}){var o;return ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,name:n??((o=this.config.user)==null?void 0:o.name)??null})}async confirmSignIn(e,n){var i;const o=await fo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,email:e,code:n});return(i=this.config.user)!=null&&i.email||(this.config.user={email:o.email,name:o.name||void 0}),this.emit("signin",{email:o.email,name:o.name}),{email:o.email,name:o.name}}async signOut(){var o;const e=he(this.config.projectId),n=await go({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,token:e==null?void 0:e.token});return e!=null&&e.email&&((o=this.config.user)==null?void 0:o.email)===e.email&&(this.config.user=null),this.emit("signout",{email:(e==null?void 0:e.email)||null}),n}knownIssues(){var e;return zo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,sessionToken:(e=he(this.config.projectId))==null?void 0:e.token})}matchKnownIssues(e,{signal:n}={}){var o;return Oo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,q:e||"",sessionToken:(o=he(this.config.projectId))==null?void 0:o.token,signal:n})}async meToo(e,{email:n,name:o}={}){var s,l;const i=he(this.config.projectId),r=await zt();return Ho({apiBase:this.config.apiBase,apiKey:this.config.apiKey,projectId:this.config.projectId,bugId:e,reporterEmail:n||((s=this.config.user)==null?void 0:s.email),reporterName:o||((l=this.config.user)==null?void 0:l.name),metadata:{...r,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},sessionToken:i==null?void 0:i.token})}snapshot(){return{console:this.consoleBuffer.all(),network:this.networkBuffer.all(),environment:Ot()}}clear(){this.consoleBuffer.clear(),this.networkBuffer.clear()}destroy(){this.endCall(),this.teardown.forEach(e=>{try{e()}catch{}}),this.teardown=[],this.notifier=null,this.started=!1}}B=new WeakSet,ye=function(){const e=qe();if(this.emit("unread",{count:e.length,updates:e}),!!this.config.updateToast){if(!this.notifier){if(!e.length)return;this.notifier=jo({accent:this.config.accent,position:this.config.widgetPosition,onRead:n=>this.markUpdateRead(n),onReadAll:()=>this.markUpdatesRead(),onCall:this.config.voice?n=>{this.markUpdateRead(n.id),this.startCall(n.bugId)}:null}),this.teardown.push(()=>{var n;return(n=this.notifier)==null?void 0:n.destroy()})}this.notifier.render(e)}},ct=async function({title:e,description:n="",priority:o="MEDIUM",metadata:i={},media:r=[],references:s=[]}){var l,u;return{projectId:this.config.projectId,...e?{title:e}:{},description:n,priority:o,url:window.location.href,reporterEmail:(l=this.config.user)==null?void 0:l.email,reporterName:(u=this.config.user)==null?void 0:u.name,metadata:{...await zt(),release:this.config.release,environment:this.config.environment,buildId:this.config.buildId,...i,user:this.config.user||void 0,sdk:pn},logs:{console:{entries:this.consoleBuffer.all()},network:{entries:this.networkBuffer.all()}},...r.length?{attachments:r}:{},...s.length?{references:s}:{}}},Qn=async function(){const e=he(this.config.projectId);let n;try{n=await Eo({apiBase:this.config.apiBase,apiKey:this.config.apiKey,token:e==null?void 0:e.token,payload:await V(this,B,ct).call(this,{})})}catch(o){throw o.status===401&&e&&ft(this.config.projectId),o}return n.watchToken&&(mt(n.watchToken),this.config.updates&&this.startWatching()),n},jn=async function(e){if(!xt())throw new Error("[BugCatch] this browser cannot make live calls.");const n=await vt();let o,i=null;try{if(e)o=await $o({apiBase:this.config.apiBase,bugId:e});else if(i=await V(this,B,Qn).call(this),e=i.id,o=i.live_call,!(o!=null&&o.realtime_url)){const s=new Error(`[BugCatch] the report was filed, but the team could not be rung${i.call_error?`: ${i.call_error}`:"."}`);throw s.filed=i,s.reason=i.call_error||null,s}}catch(s){for(const l of n.getTracks())l.stop();throw s}const r=await sn({realtimeUrl:o.realtime_url,stream:n,ringsUntil:o.rings_until,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),s==="missed"&&To({apiBase:this.config.apiBase,bugId:e,callId:o.call_id}),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,...l}),this.emit("call",{bugId:e,live:!0,state:s,...l})}});return this.call=r,Object.assign(r,{bugId:e,callId:o.call_id,live:!0,filed:i})},zn=function(e){var i;const n=e.incomingCall;if(!this.config.voice||!xt()||((i=this.ringing)==null?void 0:i.callId)===n.callId||this.call||this.callStarting)return;V(this,B,lt).call(this);const o=ga({call:n,accent:this.config.accent,position:this.config.widgetPosition,onAnswer:()=>{V(this,B,On).call(this,e.bugId,n)},onDecline:()=>{this.ringing=null,Pt({apiBase:this.config.apiBase,bugId:e.bugId,callId:n.callId}),this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"declined"})},onExpire:()=>{this.ringing=null,this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"missed"})}});if(this.ringing={callId:n.callId,dismiss:o},typeof this.config.onIncomingCall=="function")try{this.config.onIncomingCall({bugId:e.bugId,...n})}catch{}this.emit("incoming-call",{bugId:e.bugId,callId:n.callId,state:"ringing"})},lt=function(e){if(this.ringing&&!(e&&this.ringing.callId!==e)){try{this.ringing.dismiss()}catch{}this.ringing=null}},On=async function(e,n){if(this.ringing=null,this.call||this.callStarting)return;this.callStarting=!0;let o;try{o=await vt()}catch(r){this.callStarting=!1,Pt({apiBase:this.config.apiBase,bugId:e,callId:n.callId}),this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r});return}let i;try{i=await Io({apiBase:this.config.apiBase,bugId:e,callId:n.callId})}catch(r){for(const s of o.getTracks())s.stop();this.callStarting=!1,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"missed",error:r});return}try{const r=await sn({realtimeUrl:i.realtime_url,stream:o,onState:(s,l)=>{(s==="ended"||s==="failed"||s==="missed")&&(this.call=null),typeof this.config.onCallState=="function"&&this.config.onCallState(s,{bugId:e,live:!0,incoming:!0,...l}),this.emit("call",{bugId:e,live:!0,incoming:!0,state:s,...l})}});this.call=r,this.emit("incoming-call",{bugId:e,callId:n.callId,state:"answered"})}catch(r){for(const s of o.getTracks())s.stop();this.emit("incoming-call",{bugId:e,callId:n.callId,state:"failed",error:r})}finally{this.callStarting=!1}};const fn=new hn;return fn.Client=hn,fn});
|
|
996
996
|
//# sourceMappingURL=bugcatch.umd.js.map
|
package/package.json
CHANGED