@bugjar/reporter 0.1.1 → 0.1.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/index.browser.js +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/dist/index.browser.js
CHANGED
|
@@ -18888,7 +18888,7 @@ async function IA(t) {
|
|
|
18888
18888
|
}))
|
|
18889
18889
|
}, u = await gc(`${e}/upload-url`, {
|
|
18890
18890
|
method: "POST",
|
|
18891
|
-
headers: { "Content-Type": "application/json" },
|
|
18891
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
18892
18892
|
body: JSON.stringify({
|
|
18893
18893
|
projectKey: n,
|
|
18894
18894
|
manifest: a,
|
|
@@ -18916,7 +18916,7 @@ async function IA(t) {
|
|
|
18916
18916
|
await Promise.all(m);
|
|
18917
18917
|
const g = await gc(`${e}/reports/${c}/finalize`, {
|
|
18918
18918
|
method: "POST",
|
|
18919
|
-
headers: { "Content-Type": "application/json" },
|
|
18919
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
18920
18920
|
body: JSON.stringify({
|
|
18921
18921
|
projectKey: n,
|
|
18922
18922
|
finalizeToken: d,
|
|
@@ -19189,7 +19189,7 @@ class $A {
|
|
|
19189
19189
|
try {
|
|
19190
19190
|
const n = await fetch(
|
|
19191
19191
|
`${this.config.apiUrl}/capture-invitations/${encodeURIComponent(e)}/scope`,
|
|
19192
|
-
{ method: "GET" }
|
|
19192
|
+
{ method: "GET", headers: { Accept: "application/json" } }
|
|
19193
19193
|
);
|
|
19194
19194
|
if (!n.ok) {
|
|
19195
19195
|
const s = await n.json().catch(() => ({}));
|
package/dist/index.cjs
CHANGED
|
@@ -146,5 +146,5 @@ PERFORMANCE OF THIS SOFTWARE.
|
|
|
146
146
|
outline: none;
|
|
147
147
|
box-shadow: 0 0 0 3px ${s}, 0 6px 24px -8px rgba(0, 0, 0, 0.28);
|
|
148
148
|
}
|
|
149
|
-
`}),g.jsxs("button",{type:"button",className:"bugjar-trigger",onClick:t,children:[g.jsx(aw,{size:14,stroke:2}),e]})]})}function nw(r,e){const t=r.match(/^#([0-9a-f]{6})$/i);if(!t)return r;const i=parseInt(t[1],16),s=Math.max(0,Math.round((i>>16&255)*(1-e))),n=Math.max(0,Math.round((i>>8&255)*(1-e))),o=Math.max(0,Math.round((i&255)*(1-e)));return`#${(s<<16|n<<8|o).toString(16).padStart(6,"0")}`}function ow(r,e){const t=r.match(/^#([0-9a-f]{6})$/i);if(!t)return r;const i=parseInt(t[1],16);return`rgba(${i>>16&255}, ${i>>8&255}, ${i&255}, ${e})`}function aw({size:r=14,stroke:e=1.7}){return g.jsxs("svg",{width:r,height:r,viewBox:"0 0 24 24",fill:"none",style:{flexShrink:0},"aria-hidden":"true",children:[g.jsx("ellipse",{cx:"12",cy:"13",rx:"5",ry:"6",stroke:"currentColor",strokeWidth:e}),g.jsx("path",{d:"M12 7 V4 M9 5 l3 2 3-2 M5 11 l-2.5 -1 M5 15 l-2.5 1 M19 11 l2.5 -1 M19 15 l2.5 1 M9 18 l-2 2 M15 18 l2 2",stroke:"currentColor",strokeWidth:e,strokeLinecap:"round",strokeLinejoin:"round"})]})}function lw({children:r}){return g.jsx("div",{style:{background:"#111827",color:"white",padding:"10px 16px",borderRadius:8,fontFamily:"system-ui",fontSize:13},children:r})}function cw({color:r,url:e,onDismiss:t}){return g.jsxs("div",{style:{background:"white",padding:16,borderRadius:8,border:`2px solid ${r}`,fontFamily:"system-ui",fontSize:13,boxShadow:"0 10px 30px rgba(0,0,0,0.2)",maxWidth:320},children:[g.jsx("div",{style:{fontWeight:600,marginBottom:6},children:"Report sent — thank you!"}),e&&g.jsx("a",{href:e,target:"_blank",rel:"noreferrer",style:{color:r},children:"View in dashboard →"}),g.jsx("div",{style:{marginTop:12,textAlign:"right"},children:g.jsx(xs,{onClick:t,children:"Close"})})]})}function uw({error:r,onDismiss:e,onDownload:t}){return g.jsxs("div",{style:{background:"white",padding:16,borderRadius:8,border:"2px solid #ef4444",fontFamily:"system-ui",fontSize:13,boxShadow:"0 10px 30px rgba(0,0,0,0.2)",maxWidth:360},children:[g.jsx("div",{style:{fontWeight:600,marginBottom:6,color:"#b91c1c"},children:"Upload failed"}),g.jsx("div",{style:{color:"#4b5563",marginBottom:4,fontFamily:"ui-monospace, monospace",fontSize:12,wordBreak:"break-word"},children:r}),g.jsx("div",{style:{color:"#9ca3af",fontSize:11,lineHeight:1.5,marginTop:6},children:"Your report is still in memory. You can save it as a file and email it to support, or dismiss this toast to discard."}),g.jsxs("div",{style:{marginTop:12,display:"flex",gap:8,justifyContent:"flex-end"},children:[g.jsx(xs,{onClick:e,children:"Discard"}),g.jsx(xs,{onClick:t,children:"Download as file"})]})]})}function xs({onClick:r,children:e}){return g.jsx("button",{onClick:r,style:{background:"white",color:"#111827",border:"1px solid #d1d5db",borderRadius:6,padding:"10px 18px",fontWeight:500,fontSize:13,cursor:"pointer"},children:e})}const hw=typeof window<"u"?window.fetch.bind(window):fetch;async function fw(r){const{apiUrl:e,projectKey:t,userToken:i,captureToken:s,report:n,attachments:o}=r,a=n.rrwebEvents.length>0,l={replay:a?{sizeBytes:yw(n.rrwebEvents),durationMs:n.durationMs}:null,audio:n.audioBlob?{sizeBytes:n.audioBlob.size}:null,screenshot:{sizeBytes:n.screenshotBlob.size},attachments:o.map(p=>({filename:p.name,sizeBytes:p.size,mimeType:p.type}))},c=await Es(`${e}/upload-url`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectKey:t,manifest:l,...i?{userToken:i}:{},...s?{captureToken:s}:{}})});if(!c.ok)throw new Error(`upload-url failed: ${c.status} ${(await c.text()).slice(0,200)}`);const{reportId:u,finalizeToken:h,uploads:f}=await c.json(),d=[];f.replay&&a&&d.push(Cr(f.replay.url,new Blob([JSON.stringify(n.rrwebEvents)],{type:"application/json"}))),f.audio&&n.audioBlob&&d.push(Cr(f.audio.url,n.audioBlob)),d.push(Cr(f.screenshot.url,n.screenshotBlob));for(let p=0;p<o.length;p++){const y=o[p],b=f.attachments[p];if(!y||!b)throw new Error(`Server returned ${f.attachments.length} presigns for ${o.length} attachments`);d.push(Cr(b.url,y))}await Promise.all(d);const m=await Es(`${e}/reports/${u}/finalize`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({projectKey:t,finalizeToken:h,description:n.description,durationMs:n.durationMs,consoleLogs:n.consoleLogs,networkEvents:n.networkEvents,annotations:n.annotations,url:n.url,userAgent:n.userAgent,viewport:n.viewport,redactionSummary:n.redactionSummary,strictMode:n.strictMode,attachmentIds:f.attachments.map(p=>p.id)})});if(!m.ok)throw new Error(`finalize failed: ${m.status}`);const{dashboardUrl:w}=await m.json();return{reportId:u,dashboardUrl:w}}async function Cr(r,e){const t=await Es(r,{method:"PUT",headers:{"Content-Type":e.type||"application/octet-stream"},body:e});if(!t.ok){const i=await t.text().catch(()=>"");throw new Error(`PUT ${Yr(r)} failed: ${t.status} ${i.slice(0,160)}`)}}const xr=[200,800,3200],Ho=3e4;async function Es(r,e){let t=null;for(let i=0;i<=xr.length;i++){try{const o=await gw(r,e);if(!dw(o.status)||i===xr.length)return o}catch(o){if(t=o,i===xr.length)throw o}const s=xr[i],n=(Math.random()-.5)*.5*s;await pw(s+n)}throw t instanceof Error?t:new Error(`retryingFetch exhausted attempts for ${Yr(r)}`)}function dw(r){return r===408||r===502||r===503||r===504}function pw(r){return new Promise(e=>setTimeout(e,Math.max(0,r)))}function mw(r,e){return!r||typeof AbortSignal.any!="function"?e:AbortSignal.any([r,e])}async function gw(r,e){const t=AbortSignal.timeout(Ho),i=mw(e.signal,t);try{return await hw(r,{...e,signal:i})}catch(s){const n=(e.method??"GET").toUpperCase();if(t.aborted&&!e.signal?.aborted)throw new Error(`${n} ${Yr(r)} timed out after ${Ho/1e3}s`);const a=s,l=a?.cause instanceof Error?`: ${a.cause.message}`:a?.cause?`: ${String(a.cause)}`:"",c=s instanceof Error?s.message:String(s);throw new Error(`${n} ${Yr(r)} failed: ${c}${l}`)}}function Yr(r){try{const e=new URL(r),t=e.pathname.length>60?`${e.pathname.slice(0,57)}…`:e.pathname;return`${e.host}${t}`}catch{return r.slice(0,80)}}function yw(r){try{return new Blob([JSON.stringify(r)]).size}catch{return 0}}async function ww(r,e){const t={reportId:r.reportId,createdAt:r.createdAt,durationMs:r.durationMs,description:r.description,url:r.url,userAgent:r.userAgent,viewport:r.viewport,consoleLogs:r.consoleLogs,networkEvents:r.networkEvents,annotations:r.annotations,redactionSummary:r.redactionSummary,strictMode:r.strictMode,attachmentNames:e.map(n=>n.name)},i=new Blob([JSON.stringify({manifest:t,rrwebEvents:r.rrwebEvents},null,2)],{type:"application/json"}),s=document.createElement("a");s.href=URL.createObjectURL(i),s.download=`bugjar-report-${r.reportId}.json`,s.click(),URL.revokeObjectURL(s.href)}class bw{constructor(){k(this,"config",null);k(this,"root",null);k(this,"host",null);k(this,"markupHost",null);k(this,"markupController",null);k(this,"consoleCapture",null);k(this,"networkCapture",null);k(this,"recorder",null);k(this,"view","idle");k(this,"isRecording",!1);k(this,"elapsedMs",0);k(this,"capturedReport",null);k(this,"preview",null);k(this,"previewObjectUrls",[]);k(this,"error",null);k(this,"failedAttachments",null);k(this,"errorObserved",!1);k(this,"sessionId",null);k(this,"persistedActiveMs",0);k(this,"resumingToast",null);k(this,"lastRecording",null);k(this,"finalizingInFlight",!1)}init(e){if(this.config)return this.publicApi();this.config=vw(e),this.host=document.createElement("div"),this.host.setAttribute("data-bugjar-block","true"),this.host.id="bugjar-root",document.body.appendChild(this.host),this.root=Ii(this.host);const t=()=>this.onErrorObserved();this.consoleCapture=Tc(this.config.capture.consoleBufferSize,t),this.networkCapture=$c(this.config.capture.networkBufferSize,t);const i=Sw(this.config.captureTokenParam);return i&&this.applyCaptureToken(i),this.render(),this.attemptRecovery(),this.publicApi()}async attemptRecovery(){if(!this.config)return;const e=this.config.projectKey,t=Zc(e);if(!t)return;if(!Xc(t)){We(e);try{await Yt(t.sessionId)}catch{}return}let i=null;try{i=await Uc(t.sessionId)}catch{We(e);return}if(!i){We(e);return}const s=Math.max(0,i.maxDurationMs-i.activeMs);if(s<500){We(e);try{await Yt(i.sessionId)}catch{}return}try{this.consoleCapture.hydrate(i.consoleEntries),this.networkCapture.hydrate(i.networkEvents)}catch(o){this.config.onError?.(o instanceof Error?o:new Error(String(o)))}this.sessionId=i.sessionId,this.persistedActiveMs=i.activeMs,this.view="active",this.isRecording=!0,this.elapsedMs=i.activeMs,this.resumingToast={remainingMs:s},this.ensureMarkupLayer(),this.render();const n=new pn({sessionId:i.sessionId,projectKey:e,persistedActiveMs:i.activeMs,strictMode:this.config.strictMode,disabledCategories:this.config.disabledCategories,captureMicrophone:this.config.capture.captureMicrophone,maxDurationSec:this.config.capture.maxDurationSec,consoleCapture:this.consoleCapture,networkCapture:this.networkCapture,onTick:o=>{this.elapsedMs=o,this.render()},onStop:o=>{this.lastRecording={events:o.events,audioBlob:o.audioBlob,durationMs:o.durationMs},this.isRecording=!1,this.recorder=null,this.render()}});n.hydrateEvents(i.events),n.hydrateAudioChunks(i.audioChunks),this.recorder=n;try{await n.start()}catch(o){this.recorder=null,this.sessionId=null,this.persistedActiveMs=0,this.isRecording=!1,this.view="idle",this.resumingToast=null,We(e);try{await Yt(i.sessionId)}catch{}this.config.onError?.(o instanceof Error?o:new Error(String(o))),this.render();return}window.setTimeout(()=>{this.resumingToast=null,this.render()},3500)}onErrorObserved(){this.errorObserved||(this.errorObserved=!0,this.render())}publicApi(){return{open:()=>this.open(),close:()=>this.close()}}async applyCaptureToken(e){if(this.config&&this.config.captureToken!==e)try{const t=await fetch(`${this.config.apiUrl}/capture-invitations/${encodeURIComponent(e)}/scope`,{method:"GET"});if(!t.ok){const n=await t.json().catch(()=>({}));throw new Error(`capture-token scope fetch failed (${t.status}): ${n.error?.code??"unknown"}`)}const{disableCategories:i}=await t.json(),s=eu(i);this.config.captureToken=e,this.config.disabledCategories=s}catch(t){this.config.onError?.(t instanceof Error?t:new Error(String(t)))}}ensureMarkupLayer(){if(this.markupController)return this.markupController;const e=document.createElement("div");return e.id="bugjar-markup-layer",document.body.appendChild(e),this.markupHost=e,this.markupController=new Pc(e),this.markupController}teardownMarkupLayer(){this.markupController&&(this.markupController.destroy(),this.markupController=null),this.markupHost&&(this.markupHost.remove(),this.markupHost=null)}open(){if(!this.config)throw new Error("BugJar.init() must be called first");this.view="active",this.isRecording=!1,this.elapsedMs=0,this.lastRecording=null,this.ensureMarkupLayer(),this.render()}close(){this.view="idle",this.isRecording=!1,this.elapsedMs=0,this.capturedReport=null,this.preview=null,this.error=null,this.lastRecording=null,this.resumingToast=null,this.releasePreviewObjectUrls(),this.recorder&&(this.recorder.stop().catch(()=>{}),this.recorder=null),this.discardPersistedSession(),this.teardownMarkupLayer(),this.render()}discardPersistedSession(){if(!this.config||!this.sessionId)return;const e=this.config.projectKey,t=this.sessionId;We(e),Yt(t).catch(()=>{}),this.sessionId=null,this.persistedActiveMs=0}releasePreviewObjectUrls(){for(const e of this.previewObjectUrls)try{URL.revokeObjectURL(e)}catch{}this.previewObjectUrls=[]}render(){if(!this.root||!this.config)return;const{showTrigger:e,showOnError:t}=this.config.ui,i=e&&(this.errorObserved||!t);this.root.render(g.jsx(le.StrictMode,{children:g.jsx(rw,{projectKey:this.config.projectKey,primaryColor:this.config.ui.primaryColor,position:this.config.ui.position,maxDurationSec:this.config.capture.maxDurationSec,strictMode:this.config.strictMode,triggerVisible:i,triggerLabel:this.config.ui.triggerLabel,view:this.view,isRecording:this.isRecording,hasRecording:this.lastRecording!==null,elapsedMs:this.elapsedMs,preview:this.preview,error:this.error,resumingToast:this.resumingToast,onOpenActive:()=>this.open(),onCancel:()=>this.close(),onStartRecording:async()=>{await this.startRecording()},onStopRecording:async()=>{await this.stopRecording()},onToggleMicMute:s=>this.recorder?.toggleMic(s),onFinalize:async()=>{await this.finalizeReport()},onBackToMarkup:()=>this.backToMarkup(),onSendReport:async s=>{await this.sendReport(s)},onDownloadFailed:async()=>{await this.downloadOnDemand()},onSelectTool:s=>this.markupController?.setTool(s),onSelectColor:s=>this.markupController?.setColor(s),onUndoMarkup:()=>this.markupController?.undo()})}))}async startRecording(){if(!this.config||this.isRecording||this.recorder)return;this.discardPersistedSession(),this.isRecording=!0,this.elapsedMs=0,this.lastRecording=null,this.persistedActiveMs=0;const e=hn();this.sessionId=e;const t={sessionId:e,projectKey:this.config.projectKey,startedAt:Date.now(),activeMs:0,maxDurationMs:this.config.capture.maxDurationSec*1e3,events:[],audioChunks:[],consoleEntries:[],networkEvents:[],lastSeenAt:Date.now()};try{await zc(t)}catch(i){this.config.onError?.(i instanceof Error?i:new Error(String(i)))}this.render(),this.recorder=new pn({sessionId:e,projectKey:this.config.projectKey,persistedActiveMs:0,strictMode:this.config.strictMode,disabledCategories:this.config.disabledCategories,captureMicrophone:this.config.capture.captureMicrophone,maxDurationSec:this.config.capture.maxDurationSec,consoleCapture:this.consoleCapture,networkCapture:this.networkCapture,onTick:i=>{this.elapsedMs=i,this.render()},onStop:i=>{this.lastRecording={events:i.events,audioBlob:i.audioBlob,durationMs:i.durationMs},this.isRecording=!1,this.recorder=null,this.render()}});try{await this.recorder.start()}catch(i){await this.recorder.stop().catch(()=>{}),this.recorder=null,this.isRecording=!1,this.lastRecording=null,this.discardPersistedSession(),this.error=i instanceof Error?i.message:String(i),this.config.onError?.(i instanceof Error?i:new Error(String(i))),this.render()}}async stopRecording(){this.recorder&&await this.recorder.stop()}async finalizeReport(){if(this.config&&!this.finalizingInFlight){this.finalizingInFlight=!0;try{this.recorder&&await this.recorder.stop(),this.discardPersistedSession();const e=Jo(),t={disabledCategories:this.config.disabledCategories},i=this.lastRecording,s=i?nu(i.events,e,t):[],n=i?this.consoleCapture.snapshot().map(m=>xt(m,e,t)):[],o=i?this.networkCapture.snapshot().map(m=>{const w=xt(m,e,t);return{...w,url:Di(w.url,e)}}):[],a=await gh(),l={width:window.innerWidth,height:window.innerHeight},c=i?.audioBlob??null,u=i?.durationMs??0,h={reportId:hn(),createdAt:Date.now(),durationMs:u,rrwebEvents:s,audioBlob:c,screenshotBlob:a,consoleLogs:n,networkEvents:o,annotations:[],description:"",url:Di(location.href,e),userAgent:navigator.userAgent,viewport:l,redactionSummary:e,strictMode:this.config.strictMode};this.capturedReport=h,this.releasePreviewObjectUrls();const f=URL.createObjectURL(a),d=c?URL.createObjectURL(c):null;this.previewObjectUrls=[f,d].filter(m=>m!==null),this.preview={hasReplay:s.length>0,durationMs:u,replayEvents:s,replayEventCount:s.length,hasAudio:c!==null,audioBlobUrl:d,consoleLogs:n,networkEvents:o,redactionSummary:e,screenshotUrl:f,capturedViewport:l,pageUrl:location.href,userAgent:navigator.userAgent,reportUrl:null},this.view="preview",this.render()}finally{this.finalizingInFlight=!1}}}backToMarkup(){this.preview=null,this.capturedReport=null,this.view="active",this.render()}async sendReport(e){if(!(!this.capturedReport||!this.config)){this.capturedReport.description=e.description,this.capturedReport.annotations=e.annotations,this.view="uploading",this.render();try{const{reportId:t,dashboardUrl:i}=await fw({apiUrl:this.config.apiUrl,projectKey:this.config.projectKey,userToken:this.config.userToken,captureToken:this.config.captureToken,report:this.capturedReport,attachments:e.attachments});this.preview&&(this.preview.reportUrl=i),this.view="success",this.teardownMarkupLayer(),this.config.onReportSubmitted?.(t),this.render()}catch(t){this.error=t instanceof Error?t.message:String(t),this.failedAttachments=e.attachments,this.view="failed",this.config.onError?.(t instanceof Error?t:new Error(String(t))),this.render()}}}async downloadOnDemand(){if(this.capturedReport)try{await ww(this.capturedReport,this.failedAttachments??[])}catch(e){this.config?.onError?.(e instanceof Error?e:new Error(String(e)))}}}function vw(r){return{projectKey:r.projectKey,apiUrl:Ch,userToken:r.userToken??null,user:r.user??{id:""},strictMode:r.strictMode??!1,capture:{...vh,...r.capture??{}},ui:{...Sh,...r.ui??{}},onReportSubmitted:r.onReportSubmitted??(()=>{}),onError:r.onError??(()=>{}),captureTokenParam:r.captureTokenParam??"bugjar_capture",captureToken:null,disabledCategories:new Set}}function Sw(r){if(typeof window>"u"||!window.location)return null;try{const t=new URLSearchParams(window.location.search).get(r);return t&&t.length>0?t:null}catch{return null}}const yc=new bw,_i=yc,wc={init:r=>_i.init(r),open:()=>_i.open(),close:()=>_i.close()};typeof window<"u"&&(window.BugJar=wc);exports.BugJar=wc;exports._client=yc;
|
|
149
|
+
`}),g.jsxs("button",{type:"button",className:"bugjar-trigger",onClick:t,children:[g.jsx(aw,{size:14,stroke:2}),e]})]})}function nw(r,e){const t=r.match(/^#([0-9a-f]{6})$/i);if(!t)return r;const i=parseInt(t[1],16),s=Math.max(0,Math.round((i>>16&255)*(1-e))),n=Math.max(0,Math.round((i>>8&255)*(1-e))),o=Math.max(0,Math.round((i&255)*(1-e)));return`#${(s<<16|n<<8|o).toString(16).padStart(6,"0")}`}function ow(r,e){const t=r.match(/^#([0-9a-f]{6})$/i);if(!t)return r;const i=parseInt(t[1],16);return`rgba(${i>>16&255}, ${i>>8&255}, ${i&255}, ${e})`}function aw({size:r=14,stroke:e=1.7}){return g.jsxs("svg",{width:r,height:r,viewBox:"0 0 24 24",fill:"none",style:{flexShrink:0},"aria-hidden":"true",children:[g.jsx("ellipse",{cx:"12",cy:"13",rx:"5",ry:"6",stroke:"currentColor",strokeWidth:e}),g.jsx("path",{d:"M12 7 V4 M9 5 l3 2 3-2 M5 11 l-2.5 -1 M5 15 l-2.5 1 M19 11 l2.5 -1 M19 15 l2.5 1 M9 18 l-2 2 M15 18 l2 2",stroke:"currentColor",strokeWidth:e,strokeLinecap:"round",strokeLinejoin:"round"})]})}function lw({children:r}){return g.jsx("div",{style:{background:"#111827",color:"white",padding:"10px 16px",borderRadius:8,fontFamily:"system-ui",fontSize:13},children:r})}function cw({color:r,url:e,onDismiss:t}){return g.jsxs("div",{style:{background:"white",padding:16,borderRadius:8,border:`2px solid ${r}`,fontFamily:"system-ui",fontSize:13,boxShadow:"0 10px 30px rgba(0,0,0,0.2)",maxWidth:320},children:[g.jsx("div",{style:{fontWeight:600,marginBottom:6},children:"Report sent — thank you!"}),e&&g.jsx("a",{href:e,target:"_blank",rel:"noreferrer",style:{color:r},children:"View in dashboard →"}),g.jsx("div",{style:{marginTop:12,textAlign:"right"},children:g.jsx(xs,{onClick:t,children:"Close"})})]})}function uw({error:r,onDismiss:e,onDownload:t}){return g.jsxs("div",{style:{background:"white",padding:16,borderRadius:8,border:"2px solid #ef4444",fontFamily:"system-ui",fontSize:13,boxShadow:"0 10px 30px rgba(0,0,0,0.2)",maxWidth:360},children:[g.jsx("div",{style:{fontWeight:600,marginBottom:6,color:"#b91c1c"},children:"Upload failed"}),g.jsx("div",{style:{color:"#4b5563",marginBottom:4,fontFamily:"ui-monospace, monospace",fontSize:12,wordBreak:"break-word"},children:r}),g.jsx("div",{style:{color:"#9ca3af",fontSize:11,lineHeight:1.5,marginTop:6},children:"Your report is still in memory. You can save it as a file and email it to support, or dismiss this toast to discard."}),g.jsxs("div",{style:{marginTop:12,display:"flex",gap:8,justifyContent:"flex-end"},children:[g.jsx(xs,{onClick:e,children:"Discard"}),g.jsx(xs,{onClick:t,children:"Download as file"})]})]})}function xs({onClick:r,children:e}){return g.jsx("button",{onClick:r,style:{background:"white",color:"#111827",border:"1px solid #d1d5db",borderRadius:6,padding:"10px 18px",fontWeight:500,fontSize:13,cursor:"pointer"},children:e})}const hw=typeof window<"u"?window.fetch.bind(window):fetch;async function fw(r){const{apiUrl:e,projectKey:t,userToken:i,captureToken:s,report:n,attachments:o}=r,a=n.rrwebEvents.length>0,l={replay:a?{sizeBytes:yw(n.rrwebEvents),durationMs:n.durationMs}:null,audio:n.audioBlob?{sizeBytes:n.audioBlob.size}:null,screenshot:{sizeBytes:n.screenshotBlob.size},attachments:o.map(p=>({filename:p.name,sizeBytes:p.size,mimeType:p.type}))},c=await Es(`${e}/upload-url`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({projectKey:t,manifest:l,...i?{userToken:i}:{},...s?{captureToken:s}:{}})});if(!c.ok)throw new Error(`upload-url failed: ${c.status} ${(await c.text()).slice(0,200)}`);const{reportId:u,finalizeToken:h,uploads:f}=await c.json(),d=[];f.replay&&a&&d.push(Cr(f.replay.url,new Blob([JSON.stringify(n.rrwebEvents)],{type:"application/json"}))),f.audio&&n.audioBlob&&d.push(Cr(f.audio.url,n.audioBlob)),d.push(Cr(f.screenshot.url,n.screenshotBlob));for(let p=0;p<o.length;p++){const y=o[p],b=f.attachments[p];if(!y||!b)throw new Error(`Server returned ${f.attachments.length} presigns for ${o.length} attachments`);d.push(Cr(b.url,y))}await Promise.all(d);const m=await Es(`${e}/reports/${u}/finalize`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify({projectKey:t,finalizeToken:h,description:n.description,durationMs:n.durationMs,consoleLogs:n.consoleLogs,networkEvents:n.networkEvents,annotations:n.annotations,url:n.url,userAgent:n.userAgent,viewport:n.viewport,redactionSummary:n.redactionSummary,strictMode:n.strictMode,attachmentIds:f.attachments.map(p=>p.id)})});if(!m.ok)throw new Error(`finalize failed: ${m.status}`);const{dashboardUrl:w}=await m.json();return{reportId:u,dashboardUrl:w}}async function Cr(r,e){const t=await Es(r,{method:"PUT",headers:{"Content-Type":e.type||"application/octet-stream"},body:e});if(!t.ok){const i=await t.text().catch(()=>"");throw new Error(`PUT ${Yr(r)} failed: ${t.status} ${i.slice(0,160)}`)}}const xr=[200,800,3200],Ho=3e4;async function Es(r,e){let t=null;for(let i=0;i<=xr.length;i++){try{const o=await gw(r,e);if(!dw(o.status)||i===xr.length)return o}catch(o){if(t=o,i===xr.length)throw o}const s=xr[i],n=(Math.random()-.5)*.5*s;await pw(s+n)}throw t instanceof Error?t:new Error(`retryingFetch exhausted attempts for ${Yr(r)}`)}function dw(r){return r===408||r===502||r===503||r===504}function pw(r){return new Promise(e=>setTimeout(e,Math.max(0,r)))}function mw(r,e){return!r||typeof AbortSignal.any!="function"?e:AbortSignal.any([r,e])}async function gw(r,e){const t=AbortSignal.timeout(Ho),i=mw(e.signal,t);try{return await hw(r,{...e,signal:i})}catch(s){const n=(e.method??"GET").toUpperCase();if(t.aborted&&!e.signal?.aborted)throw new Error(`${n} ${Yr(r)} timed out after ${Ho/1e3}s`);const a=s,l=a?.cause instanceof Error?`: ${a.cause.message}`:a?.cause?`: ${String(a.cause)}`:"",c=s instanceof Error?s.message:String(s);throw new Error(`${n} ${Yr(r)} failed: ${c}${l}`)}}function Yr(r){try{const e=new URL(r),t=e.pathname.length>60?`${e.pathname.slice(0,57)}…`:e.pathname;return`${e.host}${t}`}catch{return r.slice(0,80)}}function yw(r){try{return new Blob([JSON.stringify(r)]).size}catch{return 0}}async function ww(r,e){const t={reportId:r.reportId,createdAt:r.createdAt,durationMs:r.durationMs,description:r.description,url:r.url,userAgent:r.userAgent,viewport:r.viewport,consoleLogs:r.consoleLogs,networkEvents:r.networkEvents,annotations:r.annotations,redactionSummary:r.redactionSummary,strictMode:r.strictMode,attachmentNames:e.map(n=>n.name)},i=new Blob([JSON.stringify({manifest:t,rrwebEvents:r.rrwebEvents},null,2)],{type:"application/json"}),s=document.createElement("a");s.href=URL.createObjectURL(i),s.download=`bugjar-report-${r.reportId}.json`,s.click(),URL.revokeObjectURL(s.href)}class bw{constructor(){k(this,"config",null);k(this,"root",null);k(this,"host",null);k(this,"markupHost",null);k(this,"markupController",null);k(this,"consoleCapture",null);k(this,"networkCapture",null);k(this,"recorder",null);k(this,"view","idle");k(this,"isRecording",!1);k(this,"elapsedMs",0);k(this,"capturedReport",null);k(this,"preview",null);k(this,"previewObjectUrls",[]);k(this,"error",null);k(this,"failedAttachments",null);k(this,"errorObserved",!1);k(this,"sessionId",null);k(this,"persistedActiveMs",0);k(this,"resumingToast",null);k(this,"lastRecording",null);k(this,"finalizingInFlight",!1)}init(e){if(this.config)return this.publicApi();this.config=vw(e),this.host=document.createElement("div"),this.host.setAttribute("data-bugjar-block","true"),this.host.id="bugjar-root",document.body.appendChild(this.host),this.root=Ii(this.host);const t=()=>this.onErrorObserved();this.consoleCapture=Tc(this.config.capture.consoleBufferSize,t),this.networkCapture=$c(this.config.capture.networkBufferSize,t);const i=Sw(this.config.captureTokenParam);return i&&this.applyCaptureToken(i),this.render(),this.attemptRecovery(),this.publicApi()}async attemptRecovery(){if(!this.config)return;const e=this.config.projectKey,t=Zc(e);if(!t)return;if(!Xc(t)){We(e);try{await Yt(t.sessionId)}catch{}return}let i=null;try{i=await Uc(t.sessionId)}catch{We(e);return}if(!i){We(e);return}const s=Math.max(0,i.maxDurationMs-i.activeMs);if(s<500){We(e);try{await Yt(i.sessionId)}catch{}return}try{this.consoleCapture.hydrate(i.consoleEntries),this.networkCapture.hydrate(i.networkEvents)}catch(o){this.config.onError?.(o instanceof Error?o:new Error(String(o)))}this.sessionId=i.sessionId,this.persistedActiveMs=i.activeMs,this.view="active",this.isRecording=!0,this.elapsedMs=i.activeMs,this.resumingToast={remainingMs:s},this.ensureMarkupLayer(),this.render();const n=new pn({sessionId:i.sessionId,projectKey:e,persistedActiveMs:i.activeMs,strictMode:this.config.strictMode,disabledCategories:this.config.disabledCategories,captureMicrophone:this.config.capture.captureMicrophone,maxDurationSec:this.config.capture.maxDurationSec,consoleCapture:this.consoleCapture,networkCapture:this.networkCapture,onTick:o=>{this.elapsedMs=o,this.render()},onStop:o=>{this.lastRecording={events:o.events,audioBlob:o.audioBlob,durationMs:o.durationMs},this.isRecording=!1,this.recorder=null,this.render()}});n.hydrateEvents(i.events),n.hydrateAudioChunks(i.audioChunks),this.recorder=n;try{await n.start()}catch(o){this.recorder=null,this.sessionId=null,this.persistedActiveMs=0,this.isRecording=!1,this.view="idle",this.resumingToast=null,We(e);try{await Yt(i.sessionId)}catch{}this.config.onError?.(o instanceof Error?o:new Error(String(o))),this.render();return}window.setTimeout(()=>{this.resumingToast=null,this.render()},3500)}onErrorObserved(){this.errorObserved||(this.errorObserved=!0,this.render())}publicApi(){return{open:()=>this.open(),close:()=>this.close()}}async applyCaptureToken(e){if(this.config&&this.config.captureToken!==e)try{const t=await fetch(`${this.config.apiUrl}/capture-invitations/${encodeURIComponent(e)}/scope`,{method:"GET",headers:{Accept:"application/json"}});if(!t.ok){const n=await t.json().catch(()=>({}));throw new Error(`capture-token scope fetch failed (${t.status}): ${n.error?.code??"unknown"}`)}const{disableCategories:i}=await t.json(),s=eu(i);this.config.captureToken=e,this.config.disabledCategories=s}catch(t){this.config.onError?.(t instanceof Error?t:new Error(String(t)))}}ensureMarkupLayer(){if(this.markupController)return this.markupController;const e=document.createElement("div");return e.id="bugjar-markup-layer",document.body.appendChild(e),this.markupHost=e,this.markupController=new Pc(e),this.markupController}teardownMarkupLayer(){this.markupController&&(this.markupController.destroy(),this.markupController=null),this.markupHost&&(this.markupHost.remove(),this.markupHost=null)}open(){if(!this.config)throw new Error("BugJar.init() must be called first");this.view="active",this.isRecording=!1,this.elapsedMs=0,this.lastRecording=null,this.ensureMarkupLayer(),this.render()}close(){this.view="idle",this.isRecording=!1,this.elapsedMs=0,this.capturedReport=null,this.preview=null,this.error=null,this.lastRecording=null,this.resumingToast=null,this.releasePreviewObjectUrls(),this.recorder&&(this.recorder.stop().catch(()=>{}),this.recorder=null),this.discardPersistedSession(),this.teardownMarkupLayer(),this.render()}discardPersistedSession(){if(!this.config||!this.sessionId)return;const e=this.config.projectKey,t=this.sessionId;We(e),Yt(t).catch(()=>{}),this.sessionId=null,this.persistedActiveMs=0}releasePreviewObjectUrls(){for(const e of this.previewObjectUrls)try{URL.revokeObjectURL(e)}catch{}this.previewObjectUrls=[]}render(){if(!this.root||!this.config)return;const{showTrigger:e,showOnError:t}=this.config.ui,i=e&&(this.errorObserved||!t);this.root.render(g.jsx(le.StrictMode,{children:g.jsx(rw,{projectKey:this.config.projectKey,primaryColor:this.config.ui.primaryColor,position:this.config.ui.position,maxDurationSec:this.config.capture.maxDurationSec,strictMode:this.config.strictMode,triggerVisible:i,triggerLabel:this.config.ui.triggerLabel,view:this.view,isRecording:this.isRecording,hasRecording:this.lastRecording!==null,elapsedMs:this.elapsedMs,preview:this.preview,error:this.error,resumingToast:this.resumingToast,onOpenActive:()=>this.open(),onCancel:()=>this.close(),onStartRecording:async()=>{await this.startRecording()},onStopRecording:async()=>{await this.stopRecording()},onToggleMicMute:s=>this.recorder?.toggleMic(s),onFinalize:async()=>{await this.finalizeReport()},onBackToMarkup:()=>this.backToMarkup(),onSendReport:async s=>{await this.sendReport(s)},onDownloadFailed:async()=>{await this.downloadOnDemand()},onSelectTool:s=>this.markupController?.setTool(s),onSelectColor:s=>this.markupController?.setColor(s),onUndoMarkup:()=>this.markupController?.undo()})}))}async startRecording(){if(!this.config||this.isRecording||this.recorder)return;this.discardPersistedSession(),this.isRecording=!0,this.elapsedMs=0,this.lastRecording=null,this.persistedActiveMs=0;const e=hn();this.sessionId=e;const t={sessionId:e,projectKey:this.config.projectKey,startedAt:Date.now(),activeMs:0,maxDurationMs:this.config.capture.maxDurationSec*1e3,events:[],audioChunks:[],consoleEntries:[],networkEvents:[],lastSeenAt:Date.now()};try{await zc(t)}catch(i){this.config.onError?.(i instanceof Error?i:new Error(String(i)))}this.render(),this.recorder=new pn({sessionId:e,projectKey:this.config.projectKey,persistedActiveMs:0,strictMode:this.config.strictMode,disabledCategories:this.config.disabledCategories,captureMicrophone:this.config.capture.captureMicrophone,maxDurationSec:this.config.capture.maxDurationSec,consoleCapture:this.consoleCapture,networkCapture:this.networkCapture,onTick:i=>{this.elapsedMs=i,this.render()},onStop:i=>{this.lastRecording={events:i.events,audioBlob:i.audioBlob,durationMs:i.durationMs},this.isRecording=!1,this.recorder=null,this.render()}});try{await this.recorder.start()}catch(i){await this.recorder.stop().catch(()=>{}),this.recorder=null,this.isRecording=!1,this.lastRecording=null,this.discardPersistedSession(),this.error=i instanceof Error?i.message:String(i),this.config.onError?.(i instanceof Error?i:new Error(String(i))),this.render()}}async stopRecording(){this.recorder&&await this.recorder.stop()}async finalizeReport(){if(this.config&&!this.finalizingInFlight){this.finalizingInFlight=!0;try{this.recorder&&await this.recorder.stop(),this.discardPersistedSession();const e=Jo(),t={disabledCategories:this.config.disabledCategories},i=this.lastRecording,s=i?nu(i.events,e,t):[],n=i?this.consoleCapture.snapshot().map(m=>xt(m,e,t)):[],o=i?this.networkCapture.snapshot().map(m=>{const w=xt(m,e,t);return{...w,url:Di(w.url,e)}}):[],a=await gh(),l={width:window.innerWidth,height:window.innerHeight},c=i?.audioBlob??null,u=i?.durationMs??0,h={reportId:hn(),createdAt:Date.now(),durationMs:u,rrwebEvents:s,audioBlob:c,screenshotBlob:a,consoleLogs:n,networkEvents:o,annotations:[],description:"",url:Di(location.href,e),userAgent:navigator.userAgent,viewport:l,redactionSummary:e,strictMode:this.config.strictMode};this.capturedReport=h,this.releasePreviewObjectUrls();const f=URL.createObjectURL(a),d=c?URL.createObjectURL(c):null;this.previewObjectUrls=[f,d].filter(m=>m!==null),this.preview={hasReplay:s.length>0,durationMs:u,replayEvents:s,replayEventCount:s.length,hasAudio:c!==null,audioBlobUrl:d,consoleLogs:n,networkEvents:o,redactionSummary:e,screenshotUrl:f,capturedViewport:l,pageUrl:location.href,userAgent:navigator.userAgent,reportUrl:null},this.view="preview",this.render()}finally{this.finalizingInFlight=!1}}}backToMarkup(){this.preview=null,this.capturedReport=null,this.view="active",this.render()}async sendReport(e){if(!(!this.capturedReport||!this.config)){this.capturedReport.description=e.description,this.capturedReport.annotations=e.annotations,this.view="uploading",this.render();try{const{reportId:t,dashboardUrl:i}=await fw({apiUrl:this.config.apiUrl,projectKey:this.config.projectKey,userToken:this.config.userToken,captureToken:this.config.captureToken,report:this.capturedReport,attachments:e.attachments});this.preview&&(this.preview.reportUrl=i),this.view="success",this.teardownMarkupLayer(),this.config.onReportSubmitted?.(t),this.render()}catch(t){this.error=t instanceof Error?t.message:String(t),this.failedAttachments=e.attachments,this.view="failed",this.config.onError?.(t instanceof Error?t:new Error(String(t))),this.render()}}}async downloadOnDemand(){if(this.capturedReport)try{await ww(this.capturedReport,this.failedAttachments??[])}catch(e){this.config?.onError?.(e instanceof Error?e:new Error(String(e)))}}}function vw(r){return{projectKey:r.projectKey,apiUrl:Ch,userToken:r.userToken??null,user:r.user??{id:""},strictMode:r.strictMode??!1,capture:{...vh,...r.capture??{}},ui:{...Sh,...r.ui??{}},onReportSubmitted:r.onReportSubmitted??(()=>{}),onError:r.onError??(()=>{}),captureTokenParam:r.captureTokenParam??"bugjar_capture",captureToken:null,disabledCategories:new Set}}function Sw(r){if(typeof window>"u"||!window.location)return null;try{const t=new URLSearchParams(window.location.search).get(r);return t&&t.length>0?t:null}catch{return null}}const yc=new bw,_i=yc,wc={init:r=>_i.init(r),open:()=>_i.open(),close:()=>_i.close()};typeof window<"u"&&(window.BugJar=wc);exports.BugJar=wc;exports._client=yc;
|
|
150
150
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.js
CHANGED
|
@@ -13256,7 +13256,7 @@ async function mw(r) {
|
|
|
13256
13256
|
}))
|
|
13257
13257
|
}, c = await Rs(`${e}/upload-url`, {
|
|
13258
13258
|
method: "POST",
|
|
13259
|
-
headers: { "Content-Type": "application/json" },
|
|
13259
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
13260
13260
|
body: JSON.stringify({
|
|
13261
13261
|
projectKey: t,
|
|
13262
13262
|
manifest: l,
|
|
@@ -13284,7 +13284,7 @@ async function mw(r) {
|
|
|
13284
13284
|
await Promise.all(d);
|
|
13285
13285
|
const m = await Rs(`${e}/reports/${u}/finalize`, {
|
|
13286
13286
|
method: "POST",
|
|
13287
|
-
headers: { "Content-Type": "application/json" },
|
|
13287
|
+
headers: { "Content-Type": "application/json", Accept: "application/json" },
|
|
13288
13288
|
body: JSON.stringify({
|
|
13289
13289
|
projectKey: t,
|
|
13290
13290
|
finalizeToken: h,
|
|
@@ -13557,7 +13557,7 @@ class Cw {
|
|
|
13557
13557
|
try {
|
|
13558
13558
|
const t = await fetch(
|
|
13559
13559
|
`${this.config.apiUrl}/capture-invitations/${encodeURIComponent(e)}/scope`,
|
|
13560
|
-
{ method: "GET" }
|
|
13560
|
+
{ method: "GET", headers: { Accept: "application/json" } }
|
|
13561
13561
|
);
|
|
13562
13562
|
if (!t.ok) {
|
|
13563
13563
|
const n = await t.json().catch(() => ({}));
|
package/package.json
CHANGED