@groundcover/browser 0.0.20 → 0.0.22

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.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var ee=require('error-stack-parser'),webVitals=require('web-vitals');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var ee__default=/*#__PURE__*/_interopDefault(ee);var J=console.log.bind(console),b=class i{constructor(){this.isDebugEnabled=false,this.prefix="";}static initialize(r){return i.instance||(i.instance=new i),r&&(i.instance.isDebugEnabled=r.debug??false,i.instance.prefix=r.prefix??""),i.instance}static getInstance(r){return i?.instance||i.initialize(r)}formatMessage(r){return `[${new Date().toISOString()}] ${this.prefix} ${r}`}log(r,...e){this.isDebugEnabled&&J(this.formatMessage(r),...e);}updateConfig(r){this.isDebugEnabled=r.debug??this.isDebugEnabled,this.prefix=r.prefix??this.prefix;}};var V=b.getInstance();function a(i){V.log("[error-handler.handleError] called",i,{groundcoverIgnore:true});}var $={batchSize:10,batchTimeout:1e4,eventSampleRate:1,sessionSampleRate:1,environment:"development",debug:false,maskFields:[],enabledEvents:["dom","network","error","log"],tracePropagationUrls:[]};var k=class{constructor(r){this.dsn=r.dsn,this.appId=r.appId,this.cluster=r.cluster,this.apiKey=r.apiKey,this.environment=r.environment,this.userIdentifier=r.userIdentifier||null,this.options={...$,...r.options};}getEndpoint(){return this.dsn}};var L=class{constructor(){this.generateTraceId=B(16);this.generateSpanId=B(8);this.generateId=B(16);}},A=Array(32);function B(i){return function(){for(let e=0;e<i*2;e++)A[e]=Math.floor(Math.random()*16)+48,A[e]>=58&&(A[e]+=39);return String.fromCharCode.apply(null,A.slice(0,i*2))}}var y=class i{constructor(){this.config=null;this.logger=b.getInstance();this.sessionId=null;this.idGenerator=new L;}static getInstance(){return i.instance||(i.instance=new i),i.instance}initialize(r){this.config||(this.config=new k(r));}getConfig(){return this.config?this.config:(this.logger.log("[config-manager] configuration not initialized"),null)}getSessionId(){return this.sessionId?this.sessionId:globalThis?.sessionStorage?.getItem("gcId")||""}setSessionId(r){this.sessionId=r,globalThis?.sessionStorage?.setItem("gcId",r);}updateConfig(r){if(this.logger.log("[config-manager] updateConfig called"),!this.config){this.logger.log("[config-manager] configuration not initialized");return}r?.options&&(this.logger.log("[config-manager] updating options"),this.config.options={...this.config.options,...r.options}),r?.userIdentifier&&(this.logger.log("[config-manager] updating user identifier"),this.config.userIdentifier={...this.config.userIdentifier,...r.userIdentifier});}};var g=typeof globalThis=="object"?globalThis:typeof self=="object"?self:typeof window=="object"?window:typeof global=="object"?global:{};var Z=y.getInstance(),j=new L;function Q(){return {path:g?.location?.pathname,url:g?.location?.href,title:g?.document?.title}}function T(){let i=Z?.getConfig()?.options?.eventSampleRate;return typeof i>"u"||Number.isNaN(i)?true:Math.random()<=i}function X(i,r=""){return Object.entries(i).reduce((e,[t,n])=>{let o=r?`${r}.${t}`:t;return typeof n=="object"&&n!==null?Object.assign(e,X(n,o)):e[o]=n,e},{})}function f(i){let r=Date.now()*1e6,e=j.generateId(),t=i.spanId||j.generateSpanId(),n=i.traceId||j.generateTraceId(),o=i.parentSpanId||"",c=X(i.attributes||{}),s=Q(),d={type:i.type,id:e,spanId:t,parentSpanId:o,traceId:n,attributes:{...c,location:s}};return i.span_name&&(d.span_name=i.span_name),i.type==="network"?(d.start_timestamp=i.timestamp||r,d.end_timestamp=i?.end_timestamp):d.timestamp=r,d}var N=class{constructor(){this.logger=b.getInstance();this.config=y.getInstance();}async send(r){let e=this.config.getConfig();if(e)try{if(e.options.debug){this.logger.log("Sending batch:",r,{groundcoverIgnore:!0});return}let t=e.apiKey,n=this.buildEndpoint();if(!t){this.logger.log("No API key found");return}fetch(n,{method:"POST",headers:{"Content-Type":"application/json",apikey:t},body:JSON.stringify(r)});}catch(t){e.options.debug&&this.logger.log("Failed to send batch:",t,{groundcoverIgnore:true});}}buildEndpoint(){let r=this.config.getConfig();if(!r)return "";let{dsn:e}=r;return `${e}/json/rum`}};var R=class R{constructor(){this.events=[];this.timeoutId=null;this.config=y.getInstance();this.initialized=false;this.transporter=new N;}static getInstance(){return R.instance||(R.instance=new R),R.instance}initialize(){try{if(this.initialized)return;this.scheduleFlush(),globalThis.addEventListener("unload",()=>{this.flush();}),this.initialized=!0;}catch(r){a(r);}}addEvent(r){if(!r||!this.initialized)return;this.events.push(r);let e=this.config.getConfig()?.options?.batchSize||100;this.events.length>=e&&this.flush();}flush(){try{if(this.events.length===0||!this.initialized)return;this.transporter.send({sessionAttributes:this.getSessionAttributes(),events:this.events}),this.events=[],this.scheduleFlush();}catch(r){a(r);}}scheduleFlush(){try{this.timeoutId!==null&&(g.clearTimeout(this.timeoutId),this.timeoutId=null);let r=this.config.getConfig()?.options?.batchTimeout;if(!r)return;this.timeoutId=g.setTimeout(()=>{this.timeoutId=null,this.flush();},r);}catch(r){a(r);}}detectBrowser(){let r=navigator.userAgent,e="unknown",t="unknown",n=navigator.platform||"unknown",o=/Mobile|Android|iPhone|iPad|iPod/i.test(r);return /Edg/.test(r)?(e="Edge",t=r.match(/Edg\/([\d.]+)/)?.[1]||t):/Chrome/.test(r)&&!/Chromium/.test(r)?(e="Chrome",t=r.match(/Chrome\/([\d.]+)/)?.[1]||t):/Firefox/.test(r)?(e="Firefox",t=r.match(/Firefox\/([\d.]+)/)?.[1]||t):/Safari/.test(r)&&!/Chrome/.test(r)?(e="Safari",t=r.match(/Version\/([\d.]+)/)?.[1]||t):/Trident/.test(r)?(e="Internet Explorer",/rv:([^)]+)\)/i.test(r)?t=r.match(/rv:([^)]+)\)/i)?.[1]||t:t=r.match(/MSIE ([^;]+)/)?.[1]||t):/OPR/.test(r)&&(e="Opera",t=r.match(/OPR\/([\d.]+)/)?.[1]||t),{name:e,version:t,platform:n,language:navigator.language,mobile:o}}getSessionAttributes(){let r=this.detectBrowser();return {cluster:this.config.getConfig()?.cluster||"",env:this.config.getConfig()?.environment||"",session_id:this.config.getSessionId(),user:this.config.getConfig()?.userIdentifier||{},"service.name":this.config.getConfig()?.appId,userAgent:navigator.userAgent,browser:r}}};R.instance=null;var w=R;var E=class{constructor(){this.logger=b.getInstance();this.eventsPool=w.getInstance();}};function C({text:i,maxLength:r=1e4}){return i?i.length<=r||typeof i!="string"?i:i.substring(0,r):""}var q=class extends E{constructor(){super(...arguments);this.eventHandlers=[];this.capturedEvents=["click","change","keydown","select","submit"];this.getShouldMaskText=e=>[e.target?.type==="password",e.target?.id?.toLowerCase().includes("password"),e.target?.id?.toLowerCase().includes("credit-card"),e.target?.id?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.getAttribute("data-private")].some(n=>n);this.getKeyCode=e=>{if(e instanceof KeyboardEvent&&e.code&&e.key!=="Dead"){let t=this.getShouldMaskText({target:e.target});return t||t?"*":e.key}return ""};this.getText=e=>{let t=e.target;return C({text:t.innerText||""})};this.getSelector=e=>e.target instanceof Element&&this.generateSelector(e.target)||"";this.getCoordinates=e=>{if({mouseup:true,mousedown:true,mousemove:true,mouseover:true}[e.type]){let{clientX:n,clientY:o}=e||{};return {clientX:n,clientY:o}}return null};}initialize(){try{this.logger.log("[dom-events-listener.initialize] called"),this.capturedEvents?.forEach(e=>{let t=n=>{try{this.handleEvent(n);}catch(o){a(o);}};this.eventHandlers.push({type:e,handler:t}),g?.addEventListener(e,t);});}catch(e){a(e);}}destroy(){this.eventHandlers.forEach(({type:e,handler:t})=>{global?.removeEventListener?.(e,t);}),this.eventHandlers=[];}handleEvent(e){try{if(!T())return;let n=this.buildEvent(e);this.queueEvent(n);}catch(t){a(t);}}buildEvent(e){let t=this.getSelector(e),n=this.getCoordinates(e),o=e.target,c=this.getKeyCode(e),s=this.getText(e);this.logger.log("[dom-events-listener.buildEvent] called");let d={dom_event_selector:t,dom_event_key_code:c,dom_event_type:e.type,dom_event_coordinates:n||{clientX:0,clientY:0},dom_event_target:{id:o.id,tagName:o.tagName,className:o.className,text:s}};return f({type:"dom.event",attributes:d})}queueEvent(e){try{this.logger.log("[dom-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}generateSelector(e,t={}){if(!e||!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return "";let n=t.root||document.body||document.documentElement,o=t.maxAttempts||10,c=t.priorityAttributes||["id","class","name","aria-label","type","title","alt"];if(e.tagName?.toLowerCase()==="html")return "html";let s="",d=0,l=e,v=[];for(;l&&l!==n&&l!==document.documentElement&&d<o;){let p=l.tagName?.toLowerCase()||"";try{let h=l.getAttribute("id");if(h&&/^[a-zA-Z][\w-]*$/.test(h))return `#${h}`;if(l.classList?.length){let u=Array.from(l.classList).filter(m=>m&&typeof m=="string").map(m=>`.${m}`);u.length&&(p+=u.join(""));}for(let u of c)if(!(u==="id"||u==="class"))try{let m=l.getAttribute(u);m&&(p+=`[${u}="${m.replace(/"/g,'\\"')}"]`);}catch{}}catch{p=l.tagName?.toLowerCase()||"*";}v.unshift(p||"*"),s=v.join(" > ");try{if(n.querySelectorAll(s).length===1)return s}catch{v.shift(),s=v.join(" > ");}try{l=l.parentElement;}catch{break}d++;}return s||"*"}};var F=["log","info","warn","error","assert","trace"],z=class extends E{constructor(){super(...arguments);this.originalConsole=null;this.isInitialized=false;}initialize(){if(!this.isInitialized)try{this.originalConsole=this.captureConsoleMethods(),F.forEach(e=>{e in console&&(console[e]=(...t)=>{try{this.handleEvent(t,e);}catch(n){a(n);}finally{this.originalConsole?.[e]&&this.originalConsole[e](...t);}});}),this.isInitialized=!0;}catch(e){a(e);}}destroy(){try{if(!this.isInitialized)return;F.forEach(e=>{this.originalConsole&&this.originalConsole[e]&&(console[e]=this.originalConsole[e]);}),this.isInitialized=!1;}catch(e){a(e);}}handleEvent(e,t){try{if(!T())return;let o=this.formatMessage(Array.isArray(e)?e:[e]);if(!o||o?.includes("groundcoverIgnore"))return;let c=this.buildEvent({message:o,level:t});this.queueEvent(c);}catch(n){a(n);}}buildEvent({message:e,level:t}){return f({type:"log",attributes:{message:C({text:e}),level:t}})}queueEvent(e){try{this.logger.log("[logs-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}formatMessage(e){if(!Array.isArray(e))return String(e);try{return e.map(t=>{if(t===void 0)return "undefined";if(t===null)return "null";if(typeof t=="object")try{return JSON.stringify(t)}catch{return Object.prototype.toString.call(t)}return String(t)}).join(" ")}catch(t){return a(t),"[Error formatting console message]"}}captureConsoleMethods(){let e={};try{F.forEach(t=>{console&&typeof console[t]=="function"&&(e[t]=console[t].bind(console));});}catch(t){a(t);}return e}};var M=class extends E{constructor(){super(...arguments);this.config=y.getInstance();this.idGenerator=new L;this.handleEvent=(e,t={})=>{try{let n=this.config.getConfig()?.dsn;if(n&&e.url?.includes(n)||!T())return;let c=this.buildEvent(e,t);this.queueEvent(c);}catch(n){a(n);}};this.buildEvent=(e,t={})=>{let n=e.url,o=e.url;this.logger.log("[network-events-listener.buildEvent] called",{event:e});try{n=new URL(e.url).pathname;}catch{o=new URL(e.url,globalThis.location.href).href;}this.logger.log("[network-events-listener.buildEvent] fullUrl",{fullUrl:o});let c=this.formatHeaders(e.request.headers),s={type:"HTTP",operation:{name:e.method},resource_name:n,status:e.status?.toString(),subType:e.method,http:{url:{full:o},route:n,path:n,method:e.method,status:e.status?.toString(),request:{headers:c,method:e.method},response:{headers:c,status_code:e.status?.toString()}},error:e?.error?.type?{type:e.error?.type||"Unknown error"}:void 0,gc:{request:{body:e.request.body},response:{body:e.response.body}}};return f({type:"network",timestamp:e?.timestamp&&!Number.isNaN(e.timestamp)?e.timestamp*1e6:void 0,end_timestamp:e?.end_time&&!Number.isNaN(e.end_time)?e.end_time*1e6:void 0,span_name:`${e.method} ${n}`,attributes:s,traceId:t?.traceId,spanId:t?.spanId})};}initialize(){this.logger.log("[network-events-listener.initialize] called"),this.patchXHR(),this.patchFetch();}destroy(){globalThis.XMLHttpRequest.prototype.open=globalThis.XMLHttpRequest.prototype.open,globalThis.XMLHttpRequest.prototype.send=globalThis.XMLHttpRequest.prototype.send,globalThis.fetch=globalThis.fetch;}queueEvent(e){try{this.logger.log("[network-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}patchXHR(){let e=this,t=globalThis.XMLHttpRequest.prototype.open,n=globalThis.XMLHttpRequest.prototype.send,o=globalThis.XMLHttpRequest.prototype.setRequestHeader,c,s={traceId:"",spanId:""};globalThis.XMLHttpRequest.prototype.open=function(d,l,v=true,p,h){if(c=Date.now(),e.shouldIgnoreRequest(l.toString()))return t.apply(this,[d,l,v,p,h]);let u=new URL(l.toString(),globalThis.location.href).href;return this._requestMethod=d,this._requestUrl=u,this._requestHeaders={},t.apply(this,[d,l,v,p,h])},globalThis.XMLHttpRequest.prototype.setRequestHeader=function(d,l){return this._requestHeaders&&(this._requestHeaders[d]=l),o.apply(this,[d,l])},globalThis.XMLHttpRequest.prototype.send=function(...d){let l=this._requestUrl.toString();if(!l||e.shouldIgnoreRequest(l))return n.apply(this,d);if(e.shouldAddTraceHeader(l)){let p=e.getTraceparentHeader();s=p,p&&(this.setRequestHeader("traceparent",p.traceparent),this._requestHeaders.traceparent=p.traceparent);}return this._requestBody=d[0]||"",this.addEventListener("load",()=>{let p=Date.now(),h={};this.getAllResponseHeaders().split(/\r?\n/).forEach(m=>{let[I,S]=m.split(": ");I&&S&&(h[I.trim()]=S.trim());});let u={timestamp:c,end_time:p,method:this._requestMethod,url:this._requestUrl,body:this._requestBody,status:this.status,request:{headers:this._requestHeaders||{},body:this._requestBody},response:{headers:h,body:this.responseText||this.response||""}};e.handleEvent(u,{traceId:s.traceId,spanId:s.spanId});}),n.apply(this,d)};}patchFetch(){let e={traceId:"",spanId:""},t=globalThis.fetch;globalThis.fetch=(...n)=>{let o=Date.now(),[c,s={}]=n,d=s?.method||"GET",l=s?.body||"",v=c instanceof Request?c.url:c.toString();if(this.shouldIgnoreRequest(v))return t.apply(globalThis,n);let p=this.shouldAddTraceHeader(v);if(s&&!s.headers&&(s.headers={}),p){let u=this.getTraceparentHeader();e=u,u&&(s?.headers instanceof Headers?s.headers.set("traceparent",u.traceparent):s.headers={...s.headers,traceparent:u.traceparent});}let h={};return s?.headers&&(s.headers instanceof Headers?s.headers.forEach((u,m)=>{h[m]=u;}):typeof s.headers=="object"&&Object.assign(h,s.headers)),t.apply(globalThis,n).then(async u=>{let m=Date.now(),I=u.clone(),S="";try{S=await I.text();}catch{S="[unreadable response body]";}let x={};I.headers.forEach((G,W)=>{x[W]=G;}),this.logger.log("[network-events-listener.patchFetch] called",{url:v});let Y={method:d,url:v,timestamp:o,body:l.toString(),status:I.status,end_time:m,request:{headers:h,body:l.toString()},response:{headers:x,body:S}};return this.handleEvent(Y,{traceId:e.traceId,spanId:e.spanId}),u}).catch(u=>{let m=Date.now(),I="NetworkError",S=u.message||"Unknown network error";u instanceof TypeError&&S.includes("Failed to fetch")?I="ERR_NETWORK_FAILURE":S.includes("Name not resolved")?I="ERR_NAME_NOT_RESOLVED":S.includes("Connection refused")&&(I="ERR_CONNECTION_REFUSED");let x={method:d,url:v,body:l.toString(),status:0,end_time:m,request:{headers:h,body:l.toString()},response:{headers:{},body:""},error:{type:I}};throw this.handleEvent(x,{traceId:e.traceId,spanId:e.spanId}),u})};}formatHeaders(e){let t=["authorization","cookie","set-cookie"];return Object.entries(e)?.reduce((n,[o,c])=>{let s=o.toLowerCase();return t.includes(s)||/(token|key|secret|password)/i.test(s)?n[o]="[REDACTED]":n[o]=C({text:c}),n},{})}shouldIgnoreRequest(e){return [".tsx",".jsx",".css"].some(n=>e.toLowerCase().endsWith(n))}getTraceparentHeader(){let e=this.idGenerator.generateSpanId(),t=this.idGenerator.generateTraceId();return {traceparent:`00-${t}-${e}-01`,traceId:t,spanId:e}}shouldAddTraceHeader(e){let t=this.config.getConfig();if(this.logger.log("[network-events-listener.shouldAddTraceHeader] called",{url:e,config:t}),!t||!t.options.tracePropagationUrls||!t.options.tracePropagationUrls?.length)return false;let n=t.options.tracePropagationUrls.some(o=>{let c=o.replace(/\*/g,".*"),s=new RegExp(`^${c}$`),l=e.startsWith("/")?new URL(e,globalThis.location.href).pathname:e;return s.test(l)});return this.logger.log("[network-events-listener.shouldAddTraceHeader] result",{url:e,result:n}),n}};var P=class extends E{constructor(){super(...arguments);this.handleEvent=(e,t)=>{this.logger.log("[errors-events-listener.handleEvent] called");try{let n;if(e instanceof Error)n=e,this.enhanceError(n);else if(e instanceof ErrorEvent){if(n=e.error||new Error(e.message||"Unknown error"),/Script error\.?/.test(n.message))return;this.enhanceError(n,e);}else if(e instanceof PromiseRejectionEvent)n=this.createUnhandledRejectionError(e);else return;let o=this.buildEvent(n,t);this.queueEvent(o);}catch(n){a(n);}};}initialize(){g?.addEventListener("error",this.handleEvent),g?.addEventListener("unhandledrejection",this.handleEvent);}destroy(){g?.removeEventListener("error",this.handleEvent),g?.removeEventListener("unhandledrejection",this.handleEvent);}buildEvent(e,t){let n={error_type:e.name||"Error",error_message:e.message||"Unknown error",error_stacktrace:this.buildStackTrace(e),error_fingerprint:`${e.name}:${C({text:e.message,maxLength:400})}`,error_handled:t?.handled||false};return f({type:"exception",attributes:n})}queueEvent(e){try{this.logger.log("[errors-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}enhanceError(e,t){let{filename:n,lineno:o,colno:c}=t||{};n&&!e.fileName&&Object.defineProperty(e,"fileName",{value:n}),o&&!e.lineNumber&&Object.defineProperty(e,"lineNumber",{value:o}),c&&!e.columnNumber&&Object.defineProperty(e,"columnNumber",{value:c});}createUnhandledRejectionError(e){let t;if(e.reason instanceof Error)t=e.reason;else {let n=typeof e.reason=="object"?JSON.stringify(e.reason,null,2):String(e.reason);t=new Error(n),t.name="UnhandledRejection",Object.defineProperty(t,"originalReason",{value:e.reason,enumerable:false});}return t}buildStackTrace(e){if(!e)return [];try{return ee__default.default.parse(e).map(n=>({filename:n.fileName||"unknown",function:n.functionName||"anonymous",lineno:n.lineNumber||0,colno:n.columnNumber||0}))}catch{return []}}};var D=class extends E{constructor(){super(...arguments);this.currentUrl=globalThis.location.href;this.mutationObserver=null;}initialize(){if(g.MutationObserver){let e=g.document.querySelector("body");e&&(this.mutationObserver=new MutationObserver(()=>{this.handleUrlChange();}),this.mutationObserver.observe(e,{childList:true,subtree:true}));}g?.addEventListener("popstate",()=>{this.handleUrlChange();});}destroy(){this.mutationObserver?.disconnect(),this.mutationObserver=null;}handleEvent(){try{this.logger.log("[navigation-listener.handleEvent] called");let e=this.buildEvent();this.queueEvent(e);}catch(e){a(e);}}buildEvent(){let e={page_url:globalThis.location.href};return f({type:"navigation",attributes:e})}queueEvent(e){try{this.logger.log("[navigation-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}handleUrlChange(){this.logger.log("[navigation-listener.handleUrlChange] called");let e=new URL(globalThis.location.href),t=new URL(this.currentUrl);e.pathname!==t.pathname&&(this.currentUrl=globalThis.location.href,this.handleEvent());}};var H=class extends E{constructor(){super(),this.startTime=performance.now();}initialize(){try{this.logger.log("[page-load-listener.initialize] called"),g?.addEventListener("load",()=>{this.handleEvent();});}catch(r){a(r);}}destroy(){g?.removeEventListener("load",this.handleEvent);}handleEvent(){try{this.logger.log("[page-load-listener.handleEvent] called");let r=this.buildEvent();this.queueEvent(r);}catch(r){a(r);}}buildEvent(){let r=performance.now()-this.startTime,e=performance.getEntriesByType("resource"),t={count:e.length,totalSize:0,totalDuration:0,byType:{}};e.forEach(o=>{let c=o,s=c.transferSize||0,d=c.duration,l=c.initiatorType;t.totalSize+=s,t.totalDuration+=d,t.byType[l]||(t.byType[l]={count:0,size:0,duration:0}),t.byType[l].count++,t.byType[l].size+=s,t.byType[l].duration+=d;});let n={page_url:g?.location?.href||"",page_load_time:r,page_referrer:g?.document?.referrer||"",page_resources:t};return f({type:"pageload",attributes:n})}queueEvent(r){try{this.logger.log("[page-load-listener.queueEvent] called"),r&&this.eventsPool.addEvent(r);}catch(e){a(e);}}};var U=class extends E{constructor(){super(...arguments);this.handleEvent=e=>{try{if(!T())return;let n=this.buildEvent(e);this.queueEvent(n);}catch(t){a(t);}};}initialize(){webVitals.onCLS(this.handleEvent),webVitals.onLCP(this.handleEvent),webVitals.onFCP(this.handleEvent),webVitals.onTTFB(this.handleEvent),webVitals.onINP(this.handleEvent);}destroy(){}buildEvent(e){let t={performance_metric_name:e.name,performance_metric_value:e.value,performance_metric_id:e.id,performance_metric_navigation_type:e.navigationType||""};return f({type:"performance",attributes:t})}queueEvent(e){try{this.logger.log("[performance-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}};var O=class{constructor(){this.logger=b.getInstance();this.eventsPool=w.getInstance();this.logEventsListener=null;this.domEventsListener=null;this.errorsEventsListener=null;this.networkEventsListener=null;this.navigationListener=null;this.performanceListener=null;this.pageLoadListener=null;}instrument(){this.logger.log("[instrumentation-manager.instrument] called"),this.domEventsListener=new q,this.logEventsListener=new z,this.errorsEventsListener=new P,this.networkEventsListener=new M,this.navigationListener=new D,this.performanceListener=new U,this.pageLoadListener=new H,this.domEventsListener.initialize(),this.logEventsListener.initialize(),this.errorsEventsListener.initialize(),this.networkEventsListener.initialize(),this.navigationListener.initialize(),this.performanceListener.initialize(),this.pageLoadListener.initialize(),this.logger.log("[instrumentation-manager.instrument] initialized listeners");}sendCustomEvent(r){this.logger.log("[instrumentation-manager.sendCustomEvent] called",r);try{let e=f({type:"custom",attributes:{custom_event_name:r?.event,custom_user:r?.attributes}});this.eventsPool.addEvent(e);}catch(e){a(e);}}captureException(r){try{this.logger.log("[instrumentation-manager.captureException] called",r),this.errorsEventsListener?.handleEvent(r,{handled:!0});}catch(e){a(e);}}uninstrument(){this.domEventsListener?.destroy(),this.logEventsListener?.destroy(),this.errorsEventsListener?.destroy(),this.networkEventsListener?.destroy(),this.navigationListener?.destroy(),this.performanceListener?.destroy();}};var K=class{constructor(r){this.initialized=false;if(this.logger=b.initialize({debug:r.options?.debug||false,prefix:"[groundcover]"}),this.logger.log("[session-manager] initialize called"),this.instrumentationManager=new O,this.idGenerator=new L,!(r.options?.sessionSampleRate?Math.random()<r.options?.sessionSampleRate:true)){this.logger.log("[session-manager] session is not sampled");return}if(this.initialized){this.logger.log("[session-manager] SDK already initialized");return}let t=y.getInstance();t.initialize(r),w.getInstance().initialize(),t.getSessionId()||t.setSessionId(this.idGenerator.generateId()),this.instrumentationManager.instrument(),this.initialized=true;}identifyUser(r){if(this.logger.log("[session-manager] identifyUser called"),!this.initialized){this.logger.log("[session-manager] cannot identify user: SDK not initialized");return}y.getInstance().updateConfig({userIdentifier:r});}sendCustomEvent(r){if(!this.initialized){this.logger.log("[session-manager] cannot send custom event: SDK not initialized");return}this.instrumentationManager.sendCustomEvent(r);}captureException(r){if(!this.initialized){this.logger.log("[session-manager] Cannot capture exception: SDK not initialized");return}this.instrumentationManager.captureException(r);}destroy(){this.initialized&&(this.instrumentationManager.uninstrument(),globalThis.sessionStorage?.removeItem("gcId"),this.initialized=false);}};var _;function se(i){try{_=new K({cluster:i?.cluster,environment:i?.environment,dsn:i?.dsn,appId:i?.appId,userIdentifier:i?.userIdentifier,apiKey:i?.apiKey,options:i?.options});}catch(r){a(r);}}function ae(i){if(!_){console.warn("[groundcover] identifyUser: groundcover is not initialized. please call init() first");return}_.identifyUser(i);}function le(i){_&&_.sendCustomEvent(i);}function ce(i){_&&_.captureException(i);}var Gt={init:se,identifyUser:ae,sendCustomEvent:le,captureException:ce};module.exports=Gt;
1
+ "use strict";var e=require("error-stack-parser"),t=require("web-vitals");function n(e){return e&&e.__esModule?e:{default:e}}var s=n(e),i=console.log.bind(console),r=class e{constructor(){this.isDebugEnabled=!1,this.prefix=""}static initialize(t){return e.instance||(e.instance=new e),t&&(e.instance.isDebugEnabled=t.debug??!1,e.instance.prefix=t.prefix??""),e.instance}static getInstance(t){return e?.instance||e.initialize(t)}formatMessage(e){return`[${(new Date).toISOString()}] ${this.prefix} ${e}`}log(e,...t){this.isDebugEnabled&&i(this.formatMessage(e),...t)}updateConfig(e){this.isDebugEnabled=e.debug??this.isDebugEnabled,this.prefix=e.prefix??this.prefix}},o=r.getInstance();function a(e){o.log("[error-handler.handleError] called",e,{groundcoverIgnore:!0})}var l={batchSize:10,batchTimeout:1e4,eventSampleRate:1,sessionSampleRate:1,environment:"development",debug:!1,maskFields:[],enabledEvents:["dom","network","error","log"],tracePropagationUrls:[]},c=class{constructor(e){this.dsn=e.dsn,this.appId=e.appId,this.cluster=e.cluster,this.apiKey=e.apiKey,this.environment=e.environment,this.userIdentifier=e.userIdentifier||null,this.options={...l,...e.options}}getEndpoint(){return this.dsn}},d=class{constructor(){this.generateTraceId=u(16),this.generateSpanId=u(8),this.generateId=u(16)}},h=Array(32);function u(e){return function(){for(let t=0;t<2*e;t++)h[t]=Math.floor(16*Math.random())+48,h[t]>=58&&(h[t]+=39);return String.fromCharCode.apply(null,h.slice(0,2*e))}}var g=class e{constructor(){this.config=null,this.logger=r.getInstance(),this.sessionId=null,this.idGenerator=new d}static getInstance(){return e.instance||(e.instance=new e),e.instance}initialize(e){this.config||(this.config=new c(e))}getConfig(){return this.config?this.config:(this.logger.log("[config-manager] configuration not initialized"),null)}getSessionId(){if(this.sessionId)return this.sessionId;const e=globalThis?.sessionStorage?.getItem("gcId");return e||""}setSessionId(e){this.sessionId=e,globalThis?.sessionStorage?.setItem("gcId",e)}updateConfig(e){this.logger.log("[config-manager] updateConfig called"),this.config?(e?.options&&(this.logger.log("[config-manager] updating options"),this.config.options={...this.config.options,...e.options}),e?.userIdentifier&&(this.logger.log("[config-manager] updating user identifier"),this.config.userIdentifier={...this.config.userIdentifier,...e.userIdentifier})):this.logger.log("[config-manager] configuration not initialized")}},p="object"==typeof globalThis?globalThis:"object"==typeof self?self:"object"==typeof window?window:"object"==typeof global?global:{},m=g.getInstance(),f=new d;function v(){const e=m?.getConfig()?.options?.eventSampleRate;return!(void 0!==e&&!Number.isNaN(e))||Math.random()<=e}function y(e,t=""){return Object.entries(e).reduce(((e,[n,s])=>{const i=t?`${t}.${n}`:n;return"object"==typeof s&&null!==s?Object.assign(e,y(s,i)):e[i]=s,e}),{})}function E(e){const t=1e6*Date.now(),n=f.generateId(),s=e.spanId||f.generateSpanId(),i=e.traceId||f.generateTraceId(),r=e.parentSpanId||"",o=y(e.attributes||{}),a={path:p?.location?.pathname,url:p?.location?.href,title:p?.document?.title},l={type:e.type,id:n,spanId:s,parentSpanId:r,traceId:i,attributes:{...o,location:a}};return e.span_name&&(l.span_name=e.span_name),"network"===e.type?(l.start_timestamp=e.timestamp||t,l.end_timestamp=e?.end_timestamp):l.timestamp=t,l}var b=class{constructor(){this.logger=r.getInstance(),this.config=g.getInstance()}async send(e){const t=this.config.getConfig();if(t)try{if(t.options.debug)return void this.logger.log("Sending batch:",e,{groundcoverIgnore:!0});const n=t.apiKey,s=this.buildEndpoint();if(!n)return void this.logger.log("No API key found");fetch(s,{method:"POST",headers:{"Content-Type":"application/json",apikey:n},body:JSON.stringify(e)})}catch(e){t.options.debug&&this.logger.log("Failed to send batch:",e,{groundcoverIgnore:!0})}}buildEndpoint(){const e=this.config.getConfig();if(!e)return"";const{dsn:t}=e;return`${t}/json/rum`}},I=class e{constructor(){this.events=[],this.timeoutId=null,this.config=g.getInstance(),this.initialized=!1,this.transporter=new b}static getInstance(){return e.instance||(e.instance=new e),e.instance}initialize(){try{if(this.initialized)return;this.scheduleFlush(),globalThis.addEventListener("unload",(()=>{this.flush()})),this.initialized=!0}catch(e){a(e)}}addEvent(e){if(!e||!this.initialized)return;this.events.push(e);const t=this.config.getConfig()?.options?.batchSize||100;this.events.length>=t&&this.flush()}flush(){try{if(0===this.events.length||!this.initialized)return;this.transporter.send({sessionAttributes:this.getSessionAttributes(),events:this.events}),this.events=[],this.scheduleFlush()}catch(e){a(e)}}scheduleFlush(){try{null!==this.timeoutId&&(p.clearTimeout(this.timeoutId),this.timeoutId=null);const e=this.config.getConfig()?.options?.batchTimeout;if(!e)return;this.timeoutId=p.setTimeout((()=>{this.timeoutId=null,this.flush()}),e)}catch(e){a(e)}}detectBrowser(){const e=navigator.userAgent;let t="unknown",n="unknown";const s=navigator.platform||"unknown",i=/Mobile|Android|iPhone|iPad|iPod/i.test(e);return/Edg/.test(e)?(t="Edge",n=e.match(/Edg\/([\d.]+)/)?.[1]||n):/Chrome/.test(e)&&!/Chromium/.test(e)?(t="Chrome",n=e.match(/Chrome\/([\d.]+)/)?.[1]||n):/Firefox/.test(e)?(t="Firefox",n=e.match(/Firefox\/([\d.]+)/)?.[1]||n):/Safari/.test(e)&&!/Chrome/.test(e)?(t="Safari",n=e.match(/Version\/([\d.]+)/)?.[1]||n):/Trident/.test(e)?(t="Internet Explorer",n=/rv:([^)]+)\)/i.test(e)?e.match(/rv:([^)]+)\)/i)?.[1]||n:e.match(/MSIE ([^;]+)/)?.[1]||n):/OPR/.test(e)&&(t="Opera",n=e.match(/OPR\/([\d.]+)/)?.[1]||n),{name:t,version:n,platform:s,language:navigator.language,mobile:i}}getSessionAttributes(){const e=this.detectBrowser();return{cluster:this.config.getConfig()?.cluster||"",env:this.config.getConfig()?.environment||"",session_id:this.config.getSessionId(),user:this.config.getConfig()?.userIdentifier||{},"service.name":this.config.getConfig()?.appId,userAgent:navigator.userAgent,browser:e}}};I.instance=null;var w=I,T=class{constructor(){this.logger=r.getInstance(),this.eventsPool=w.getInstance()}};function L({text:e,maxLength:t=1e4}){return e?e.length<=t||"string"!=typeof e?e:e.substring(0,t):""}var _,S=class extends T{constructor(){super(...arguments),this.eventHandlers=[],this.capturedEvents=["click","change","keydown","select","submit"],this.getShouldMaskText=e=>["password"===e.target?.type,e.target?.id?.toLowerCase().includes("password"),e.target?.id?.toLowerCase().includes("credit-card"),e.target?.id?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.getAttribute("data-private")].some((e=>e)),this.getKeyCode=e=>{if(e instanceof KeyboardEvent&&e.code&&"Dead"!==e.key){const t=this.getShouldMaskText({target:e.target});return t||t?"*":e.key}return""},this.getText=e=>L({text:e.target.innerText||""}),this.getSelector=e=>e.target instanceof Element&&this.generateSelector(e.target)||"",this.getCoordinates=e=>{if({mouseup:!0,mousedown:!0,mousemove:!0,mouseover:!0}[e.type]){const{clientX:t,clientY:n}=e||{};return{clientX:t,clientY:n}}return null}}initialize(){try{this.logger.log("[dom-events-listener.initialize] called"),this.capturedEvents?.forEach((e=>{const t=e=>{try{this.handleEvent(e)}catch(e){a(e)}};this.eventHandlers.push({type:e,handler:t}),p?.addEventListener(e,t)}))}catch(e){a(e)}}destroy(){this.eventHandlers.forEach((({type:e,handler:t})=>{global?.removeEventListener?.(e,t)})),this.eventHandlers=[]}handleEvent(e){try{if(!v())return;const t=this.buildEvent(e);this.queueEvent(t)}catch(e){a(e)}}buildEvent(e){const t=this.getSelector(e),n=this.getCoordinates(e),s=e.target,i=this.getKeyCode(e),r=this.getText(e);this.logger.log("[dom-events-listener.buildEvent] called");return E({type:"dom.event",attributes:{dom_event_selector:t,dom_event_key_code:i,dom_event_type:e.type,dom_event_coordinates:n||{clientX:0,clientY:0},dom_event_target:{id:s.id,tagName:s.tagName,className:s.className,text:r}}})}queueEvent(e){try{this.logger.log("[dom-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}generateSelector(e,t={}){if(!e||!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return"";const n=t.root||document.body||document.documentElement,s=t.maxAttempts||10,i=t.priorityAttributes||["id","class","name","aria-label","type","title","alt"];if("html"===e.tagName?.toLowerCase())return"html";let r="",o=0,a=e;const l=[];for(;a&&a!==n&&a!==document.documentElement&&o<s;){let e=a.tagName?.toLowerCase()||"";try{const t=a.getAttribute("id");if(t&&/^[a-zA-Z][\w-]*$/.test(t))return`#${t}`;if(a.classList?.length){const t=Array.from(a.classList).filter((e=>e&&"string"==typeof e)).map((e=>`.${e}`));t.length&&(e+=t.join(""))}for(const t of i)if("id"!==t&&"class"!==t)try{const n=a.getAttribute(t);n&&(e+=`[${t}="${n.replace(/"/g,'\\"')}"]`)}catch(e){}}catch(t){e=a.tagName?.toLowerCase()||"*"}l.unshift(e||"*"),r=l.join(" > ");try{if(1===n.querySelectorAll(r).length)return r}catch(e){l.shift(),r=l.join(" > ")}try{a=a.parentElement}catch(e){break}o++}return r||"*"}},C=["log","info","warn","error","assert","trace"],q=class extends T{constructor(){super(...arguments),this.originalConsole=null,this.isInitialized=!1}initialize(){if(!this.isInitialized)try{this.originalConsole=this.captureConsoleMethods(),C.forEach((e=>{e in console&&(console[e]=(...t)=>{try{this.handleEvent(t,e)}catch(e){a(e)}finally{this.originalConsole?.[e]&&this.originalConsole[e](...t)}})})),this.isInitialized=!0}catch(e){a(e)}}destroy(){try{if(!this.isInitialized)return;C.forEach((e=>{this.originalConsole&&this.originalConsole[e]&&(console[e]=this.originalConsole[e])})),this.isInitialized=!1}catch(e){a(e)}}handleEvent(e,t){try{if(!v())return;const n=this.formatMessage(Array.isArray(e)?e:[e]);if(!n||n?.includes("groundcoverIgnore"))return;const s=this.buildEvent({message:n,level:t});this.queueEvent(s)}catch(e){a(e)}}buildEvent({message:e,level:t}){return E({type:"log",attributes:{message:L({text:e}),level:t}})}queueEvent(e){try{this.logger.log("[logs-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}formatMessage(e){if(!Array.isArray(e))return String(e);try{return e.map((e=>{if(void 0===e)return"undefined";if(null===e)return"null";if("object"==typeof e)try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}return String(e)})).join(" ")}catch(e){return a(e),"[Error formatting console message]"}}captureConsoleMethods(){const e={};try{C.forEach((t=>{console&&"function"==typeof console[t]&&(e[t]=console[t].bind(console))}))}catch(e){a(e)}return e}},z=class extends T{constructor(){super(...arguments),this.config=g.getInstance(),this.idGenerator=new d,this.handleEvent=e=>{try{const t=this.config.getConfig()?.dsn;if(t&&e.url?.includes(t))return;if(!v())return;const n=this.buildEvent(e);this.queueEvent(n)}catch(e){a(e)}},this.buildEvent=e=>{let t=e.url,n=e.url;this.logger.log("[network-events-listener.buildEvent] called",{event:e});try{t=new URL(e.url).pathname}catch(t){n=new URL(e.url,globalThis.location.href).href}this.logger.log("[network-events-listener.buildEvent] fullUrl",{fullUrl:n});const s=this.formatHeaders(e.request.headers),i=e.request.headers.traceparent,r=i?.split("-")?.[1]||"",o=i?.split("-")?.[2]||"",a={type:"HTTP",operation:{name:e.method},resource_name:t,status:e.status?.toString(),subType:e.method,http:{url:{full:n},route:t,path:t,method:e.method,status:e.status?.toString(),request:{headers:s,method:e.method},response:{headers:s,status_code:e.status?.toString()}},error:e?.error?.type?{type:e.error?.type||"Unknown error"}:void 0,gc:{request:{body:e.request.body},response:{body:e.response.body}}};return E({type:"network",timestamp:e?.timestamp&&!Number.isNaN(e.timestamp)?1e6*e.timestamp:void 0,end_timestamp:e?.end_time&&!Number.isNaN(e.end_time)?1e6*e.end_time:void 0,span_name:`${e.method} ${t}`,attributes:a,traceId:r,spanId:o})}}initialize(){this.logger.log("[network-events-listener.initialize] called"),this.patchXHR(),this.patchFetch()}destroy(){globalThis.XMLHttpRequest.prototype.open=globalThis.XMLHttpRequest.prototype.open,globalThis.XMLHttpRequest.prototype.send=globalThis.XMLHttpRequest.prototype.send,globalThis.fetch=globalThis.fetch}queueEvent(e){try{this.logger.log("[network-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}patchXHR(){const e=this,t=globalThis.XMLHttpRequest.prototype.open,n=globalThis.XMLHttpRequest.prototype.send,s=globalThis.XMLHttpRequest.prototype.setRequestHeader;let i;globalThis.XMLHttpRequest.prototype.open=function(n,s,r=!0,o,a){if(i=Date.now(),e.shouldIgnoreRequest(s.toString()))return t.apply(this,[n,s,r,o,a]);const l=new URL(s.toString(),globalThis.location.href).href;return this._requestMethod=n,this._requestUrl=l,this._requestHeaders={},t.apply(this,[n,s,r,o,a])},globalThis.XMLHttpRequest.prototype.setRequestHeader=function(e,t){return this._requestHeaders&&(this._requestHeaders[e]=t),s.apply(this,[e,t])},globalThis.XMLHttpRequest.prototype.send=function(...t){const s=this._requestUrl.toString();if(!s||e.shouldIgnoreRequest(s))return n.apply(this,t);if(e.shouldAddTraceHeader(s)){const t=e.getTraceparentHeader();t&&(this.setRequestHeader("traceparent",t.traceparent),this._requestHeaders.traceparent=t.traceparent)}return this._requestBody=t[0]||"",this.addEventListener("load",(()=>{const t=Date.now(),n={};this.getAllResponseHeaders().split(/\r?\n/).forEach((e=>{const[t,s]=e.split(": ");t&&s&&(n[t.trim()]=s.trim())}));const s={timestamp:i,end_time:t,method:this._requestMethod,url:this._requestUrl,body:this._requestBody,status:this.status,request:{headers:this._requestHeaders||{},body:this._requestBody},response:{headers:n,body:this.responseText||this.response||""}};e.handleEvent(s)})),n.apply(this,t)}}patchFetch(){const e=globalThis.fetch;globalThis.fetch=(...t)=>{const n=Date.now();let[s,i]=t;i={...i||{}};const r=i?.method||"GET",o=i?.body||"",a=s instanceof Request?s.url:s.toString();if(this.shouldIgnoreRequest(a))return e.apply(globalThis,t);const l=this.shouldAddTraceHeader(a);if(i&&!i.headers&&(i.headers={}),i||(t[1]={},i=t[1]),l){const e=this.getTraceparentHeader();e&&(i?.headers instanceof Headers?i.headers.set("traceparent",e.traceparent):i.headers={...i.headers,traceparent:e.traceparent})}const c={};return i?.headers&&(i.headers instanceof Headers?i.headers.forEach(((e,t)=>{c[t]=e})):"object"==typeof i.headers&&Object.assign(c,i.headers)),e.apply(globalThis,t).then((async e=>{const t=Date.now(),s=e.clone();let i="";try{i=await s.text()}catch(e){i="[unreadable response body]"}const l={};s.headers.forEach(((e,t)=>{l[t]=e})),this.logger.log("[network-events-listener.patchFetch] called",{url:a});const d={method:r,url:a,timestamp:n,body:o.toString(),status:s.status,end_time:t,request:{headers:c,body:o.toString()},response:{headers:l,body:i}};return this.handleEvent(d),e})).catch((e=>{const t=Date.now();let n="NetworkError";const s=e.message||"Unknown network error";e instanceof TypeError&&s.includes("Failed to fetch")?n="ERR_NETWORK_FAILURE":s.includes("Name not resolved")?n="ERR_NAME_NOT_RESOLVED":s.includes("Connection refused")&&(n="ERR_CONNECTION_REFUSED");const i={method:r,url:a,body:o.toString(),status:0,end_time:t,request:{headers:c,body:o.toString()},response:{headers:{},body:""},error:{type:n}};throw this.handleEvent(i),e}))}}formatHeaders(e){const t=["authorization","cookie","set-cookie"];return Object.entries(e)?.reduce(((e,[n,s])=>{const i=n.toLowerCase();return t.includes(i)||/(token|key|secret|password)/i.test(i)?e[n]="[REDACTED]":e[n]=L({text:s}),e}),{})}shouldIgnoreRequest(e){return[".tsx",".jsx",".css"].some((t=>e.toLowerCase().endsWith(t)))}getTraceparentHeader(){const e=this.idGenerator.generateSpanId(),t=this.idGenerator.generateTraceId();return{traceparent:`00-${t}-${e}-01`,traceId:t,spanId:e}}shouldAddTraceHeader(e){const t=this.config.getConfig();if(this.logger.log("[network-events-listener.shouldAddTraceHeader] called",{url:e,config:t}),!t||!t.options.tracePropagationUrls||!t.options.tracePropagationUrls?.length)return!1;const n=t.options.tracePropagationUrls.some((t=>{const n=t.replace(/\*/g,".*"),s=new RegExp(`^${n}$`),i=e.startsWith("/")?new URL(e,globalThis.location.href).pathname:e;return s.test(i)}));return this.logger.log("[network-events-listener.shouldAddTraceHeader] result",{url:e,result:n}),n}},R=class extends T{constructor(){super(...arguments),this.handleEvent=(e,t)=>{this.logger.log("[errors-events-listener.handleEvent] called");try{let n;if(e instanceof Error)n=e,this.enhanceError(n);else if(e instanceof ErrorEvent){if(n=e.error||new Error(e.message||"Unknown error"),/Script error\.?/.test(n.message))return;this.enhanceError(n,e)}else{if(!(e instanceof PromiseRejectionEvent))return;n=this.createUnhandledRejectionError(e)}const s=this.buildEvent(n,t);this.queueEvent(s)}catch(e){a(e)}}}initialize(){p?.addEventListener("error",this.handleEvent),p?.addEventListener("unhandledrejection",this.handleEvent)}destroy(){p?.removeEventListener("error",this.handleEvent),p?.removeEventListener("unhandledrejection",this.handleEvent)}buildEvent(e,t){return E({type:"exception",attributes:{error_type:e.name||"Error",error_message:e.message||"Unknown error",error_stacktrace:this.buildStackTrace(e),error_fingerprint:`${e.name}:${L({text:e.message,maxLength:400})}`,error_handled:t?.handled||!1}})}queueEvent(e){try{this.logger.log("[errors-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}enhanceError(e,t){const{filename:n,lineno:s,colno:i}=t||{};n&&!e.fileName&&Object.defineProperty(e,"fileName",{value:n}),s&&!e.lineNumber&&Object.defineProperty(e,"lineNumber",{value:s}),i&&!e.columnNumber&&Object.defineProperty(e,"columnNumber",{value:i})}createUnhandledRejectionError(e){let t;if(e.reason instanceof Error)t=e.reason;else{const n="object"==typeof e.reason?JSON.stringify(e.reason,null,2):String(e.reason);t=new Error(n),t.name="UnhandledRejection",Object.defineProperty(t,"originalReason",{value:e.reason,enumerable:!1})}return t}buildStackTrace(e){if(!e)return[];try{return s.default.parse(e).map((e=>({filename:e.fileName||"unknown",function:e.functionName||"anonymous",lineno:e.lineNumber||0,colno:e.columnNumber||0})))}catch(e){return[]}}},x=class extends T{constructor(){super(...arguments),this.currentUrl=globalThis.location.href,this.mutationObserver=null}initialize(){if(p.MutationObserver){const e=p.document.querySelector("body");e&&(this.mutationObserver=new MutationObserver((()=>{this.handleUrlChange()})),this.mutationObserver.observe(e,{childList:!0,subtree:!0}))}p?.addEventListener("popstate",(()=>{this.handleUrlChange()}))}destroy(){this.mutationObserver?.disconnect(),this.mutationObserver=null}handleEvent(){try{this.logger.log("[navigation-listener.handleEvent] called");const e=this.buildEvent();this.queueEvent(e)}catch(e){a(e)}}buildEvent(){return E({type:"navigation",attributes:{page_url:globalThis.location.href}})}queueEvent(e){try{this.logger.log("[navigation-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}handleUrlChange(){this.logger.log("[navigation-listener.handleUrlChange] called");const e=new URL(globalThis.location.href),t=new URL(this.currentUrl);e.pathname!==t.pathname&&(this.currentUrl=globalThis.location.href,this.handleEvent())}},N=class extends T{constructor(){super(),this.startTime=performance.now()}initialize(){try{this.logger.log("[page-load-listener.initialize] called"),p?.addEventListener("load",(()=>{this.handleEvent()}))}catch(e){a(e)}}destroy(){p?.removeEventListener("load",this.handleEvent)}handleEvent(){try{this.logger.log("[page-load-listener.handleEvent] called");const e=this.buildEvent();this.queueEvent(e)}catch(e){a(e)}}buildEvent(){const e=performance.now()-this.startTime,t=performance.getEntriesByType("resource"),n={count:t.length,totalSize:0,totalDuration:0,byType:{}};t.forEach((e=>{const t=e,s=t.transferSize||0,i=t.duration,r=t.initiatorType;n.totalSize+=s,n.totalDuration+=i,n.byType[r]||(n.byType[r]={count:0,size:0,duration:0}),n.byType[r].count++,n.byType[r].size+=s,n.byType[r].duration+=i}));return E({type:"pageload",attributes:{page_url:p?.location?.href||"",page_load_time:e,page_referrer:p?.document?.referrer||"",page_resources:n}})}queueEvent(e){try{this.logger.log("[page-load-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}},k=class extends T{constructor(){super(...arguments),this.handleEvent=e=>{try{if(!v())return;const t=this.buildEvent(e);this.queueEvent(t)}catch(e){a(e)}}}initialize(){t.onCLS(this.handleEvent),t.onLCP(this.handleEvent),t.onFCP(this.handleEvent),t.onTTFB(this.handleEvent),t.onINP(this.handleEvent)}destroy(){}buildEvent(e){return E({type:"performance",attributes:{performance_metric_name:e.name,performance_metric_value:e.value,performance_metric_id:e.id,performance_metric_navigation_type:e.navigationType||""}})}queueEvent(e){try{this.logger.log("[performance-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){a(e)}}},H=class{constructor(){this.logger=r.getInstance(),this.eventsPool=w.getInstance(),this.logEventsListener=null,this.domEventsListener=null,this.errorsEventsListener=null,this.networkEventsListener=null,this.navigationListener=null,this.performanceListener=null,this.pageLoadListener=null}instrument(){this.logger.log("[instrumentation-manager.instrument] called"),this.domEventsListener=new S,this.logEventsListener=new q,this.errorsEventsListener=new R,this.networkEventsListener=new z,this.navigationListener=new x,this.performanceListener=new k,this.pageLoadListener=new N,this.domEventsListener.initialize(),this.logEventsListener.initialize(),this.errorsEventsListener.initialize(),this.networkEventsListener.initialize(),this.navigationListener.initialize(),this.performanceListener.initialize(),this.pageLoadListener.initialize(),this.logger.log("[instrumentation-manager.instrument] initialized listeners")}sendCustomEvent(e){this.logger.log("[instrumentation-manager.sendCustomEvent] called",e);try{const t=E({type:"custom",attributes:{custom_event_name:e?.event,custom_user:e?.attributes}});this.eventsPool.addEvent(t)}catch(e){a(e)}}captureException(e){try{this.logger.log("[instrumentation-manager.captureException] called",e),this.errorsEventsListener?.handleEvent(e,{handled:!0})}catch(e){a(e)}}uninstrument(){this.domEventsListener?.destroy(),this.logEventsListener?.destroy(),this.errorsEventsListener?.destroy(),this.networkEventsListener?.destroy(),this.navigationListener?.destroy(),this.performanceListener?.destroy()}},M=class{constructor(e){this.initialized=!1,this.logger=r.initialize({debug:e.options?.debug||!1,prefix:"[groundcover]"}),this.logger.log("[session-manager] initialize called"),this.instrumentationManager=new H,this.idGenerator=new d;if(!(!e.options?.sessionSampleRate||Math.random()<e.options?.sessionSampleRate))return void this.logger.log("[session-manager] session is not sampled");if(this.initialized)return void this.logger.log("[session-manager] SDK already initialized");const t=g.getInstance();t.initialize(e);w.getInstance().initialize();t.getSessionId()||t.setSessionId(this.idGenerator.generateId()),this.instrumentationManager.instrument(),this.initialized=!0}identifyUser(e){if(this.logger.log("[session-manager] identifyUser called"),!this.initialized)return void this.logger.log("[session-manager] cannot identify user: SDK not initialized");g.getInstance().updateConfig({userIdentifier:e})}sendCustomEvent(e){this.initialized?this.instrumentationManager.sendCustomEvent(e):this.logger.log("[session-manager] cannot send custom event: SDK not initialized")}captureException(e){this.initialized?this.instrumentationManager.captureException(e):this.logger.log("[session-manager] Cannot capture exception: SDK not initialized")}destroy(){this.initialized&&(this.instrumentationManager.uninstrument(),globalThis.sessionStorage?.removeItem("gcId"),this.initialized=!1)}};var U={init:function(e){try{_=new M({cluster:e?.cluster,environment:e?.environment,dsn:e?.dsn,appId:e?.appId,userIdentifier:e?.userIdentifier,apiKey:e?.apiKey,options:e?.options})}catch(e){a(e)}},identifyUser:function(e){_?_.identifyUser(e):console.warn("[groundcover] identifyUser: groundcover is not initialized. please call init() first")},sendCustomEvent:function(e){_&&_.sendCustomEvent(e)},captureException:function(e){_&&_.captureException(e)}};module.exports=U;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import ee from'error-stack-parser';import {onCLS,onLCP,onFCP,onTTFB,onINP}from'web-vitals';var J=console.log.bind(console),b=class i{constructor(){this.isDebugEnabled=false,this.prefix="";}static initialize(r){return i.instance||(i.instance=new i),r&&(i.instance.isDebugEnabled=r.debug??false,i.instance.prefix=r.prefix??""),i.instance}static getInstance(r){return i?.instance||i.initialize(r)}formatMessage(r){return `[${new Date().toISOString()}] ${this.prefix} ${r}`}log(r,...e){this.isDebugEnabled&&J(this.formatMessage(r),...e);}updateConfig(r){this.isDebugEnabled=r.debug??this.isDebugEnabled,this.prefix=r.prefix??this.prefix;}};var V=b.getInstance();function a(i){V.log("[error-handler.handleError] called",i,{groundcoverIgnore:true});}var $={batchSize:10,batchTimeout:1e4,eventSampleRate:1,sessionSampleRate:1,environment:"development",debug:false,maskFields:[],enabledEvents:["dom","network","error","log"],tracePropagationUrls:[]};var k=class{constructor(r){this.dsn=r.dsn,this.appId=r.appId,this.cluster=r.cluster,this.apiKey=r.apiKey,this.environment=r.environment,this.userIdentifier=r.userIdentifier||null,this.options={...$,...r.options};}getEndpoint(){return this.dsn}};var L=class{constructor(){this.generateTraceId=B(16);this.generateSpanId=B(8);this.generateId=B(16);}},A=Array(32);function B(i){return function(){for(let e=0;e<i*2;e++)A[e]=Math.floor(Math.random()*16)+48,A[e]>=58&&(A[e]+=39);return String.fromCharCode.apply(null,A.slice(0,i*2))}}var y=class i{constructor(){this.config=null;this.logger=b.getInstance();this.sessionId=null;this.idGenerator=new L;}static getInstance(){return i.instance||(i.instance=new i),i.instance}initialize(r){this.config||(this.config=new k(r));}getConfig(){return this.config?this.config:(this.logger.log("[config-manager] configuration not initialized"),null)}getSessionId(){return this.sessionId?this.sessionId:globalThis?.sessionStorage?.getItem("gcId")||""}setSessionId(r){this.sessionId=r,globalThis?.sessionStorage?.setItem("gcId",r);}updateConfig(r){if(this.logger.log("[config-manager] updateConfig called"),!this.config){this.logger.log("[config-manager] configuration not initialized");return}r?.options&&(this.logger.log("[config-manager] updating options"),this.config.options={...this.config.options,...r.options}),r?.userIdentifier&&(this.logger.log("[config-manager] updating user identifier"),this.config.userIdentifier={...this.config.userIdentifier,...r.userIdentifier});}};var g=typeof globalThis=="object"?globalThis:typeof self=="object"?self:typeof window=="object"?window:typeof global=="object"?global:{};var Z=y.getInstance(),j=new L;function Q(){return {path:g?.location?.pathname,url:g?.location?.href,title:g?.document?.title}}function T(){let i=Z?.getConfig()?.options?.eventSampleRate;return typeof i>"u"||Number.isNaN(i)?true:Math.random()<=i}function X(i,r=""){return Object.entries(i).reduce((e,[t,n])=>{let o=r?`${r}.${t}`:t;return typeof n=="object"&&n!==null?Object.assign(e,X(n,o)):e[o]=n,e},{})}function f(i){let r=Date.now()*1e6,e=j.generateId(),t=i.spanId||j.generateSpanId(),n=i.traceId||j.generateTraceId(),o=i.parentSpanId||"",c=X(i.attributes||{}),s=Q(),d={type:i.type,id:e,spanId:t,parentSpanId:o,traceId:n,attributes:{...c,location:s}};return i.span_name&&(d.span_name=i.span_name),i.type==="network"?(d.start_timestamp=i.timestamp||r,d.end_timestamp=i?.end_timestamp):d.timestamp=r,d}var N=class{constructor(){this.logger=b.getInstance();this.config=y.getInstance();}async send(r){let e=this.config.getConfig();if(e)try{if(e.options.debug){this.logger.log("Sending batch:",r,{groundcoverIgnore:!0});return}let t=e.apiKey,n=this.buildEndpoint();if(!t){this.logger.log("No API key found");return}fetch(n,{method:"POST",headers:{"Content-Type":"application/json",apikey:t},body:JSON.stringify(r)});}catch(t){e.options.debug&&this.logger.log("Failed to send batch:",t,{groundcoverIgnore:true});}}buildEndpoint(){let r=this.config.getConfig();if(!r)return "";let{dsn:e}=r;return `${e}/json/rum`}};var R=class R{constructor(){this.events=[];this.timeoutId=null;this.config=y.getInstance();this.initialized=false;this.transporter=new N;}static getInstance(){return R.instance||(R.instance=new R),R.instance}initialize(){try{if(this.initialized)return;this.scheduleFlush(),globalThis.addEventListener("unload",()=>{this.flush();}),this.initialized=!0;}catch(r){a(r);}}addEvent(r){if(!r||!this.initialized)return;this.events.push(r);let e=this.config.getConfig()?.options?.batchSize||100;this.events.length>=e&&this.flush();}flush(){try{if(this.events.length===0||!this.initialized)return;this.transporter.send({sessionAttributes:this.getSessionAttributes(),events:this.events}),this.events=[],this.scheduleFlush();}catch(r){a(r);}}scheduleFlush(){try{this.timeoutId!==null&&(g.clearTimeout(this.timeoutId),this.timeoutId=null);let r=this.config.getConfig()?.options?.batchTimeout;if(!r)return;this.timeoutId=g.setTimeout(()=>{this.timeoutId=null,this.flush();},r);}catch(r){a(r);}}detectBrowser(){let r=navigator.userAgent,e="unknown",t="unknown",n=navigator.platform||"unknown",o=/Mobile|Android|iPhone|iPad|iPod/i.test(r);return /Edg/.test(r)?(e="Edge",t=r.match(/Edg\/([\d.]+)/)?.[1]||t):/Chrome/.test(r)&&!/Chromium/.test(r)?(e="Chrome",t=r.match(/Chrome\/([\d.]+)/)?.[1]||t):/Firefox/.test(r)?(e="Firefox",t=r.match(/Firefox\/([\d.]+)/)?.[1]||t):/Safari/.test(r)&&!/Chrome/.test(r)?(e="Safari",t=r.match(/Version\/([\d.]+)/)?.[1]||t):/Trident/.test(r)?(e="Internet Explorer",/rv:([^)]+)\)/i.test(r)?t=r.match(/rv:([^)]+)\)/i)?.[1]||t:t=r.match(/MSIE ([^;]+)/)?.[1]||t):/OPR/.test(r)&&(e="Opera",t=r.match(/OPR\/([\d.]+)/)?.[1]||t),{name:e,version:t,platform:n,language:navigator.language,mobile:o}}getSessionAttributes(){let r=this.detectBrowser();return {cluster:this.config.getConfig()?.cluster||"",env:this.config.getConfig()?.environment||"",session_id:this.config.getSessionId(),user:this.config.getConfig()?.userIdentifier||{},"service.name":this.config.getConfig()?.appId,userAgent:navigator.userAgent,browser:r}}};R.instance=null;var w=R;var E=class{constructor(){this.logger=b.getInstance();this.eventsPool=w.getInstance();}};function C({text:i,maxLength:r=1e4}){return i?i.length<=r||typeof i!="string"?i:i.substring(0,r):""}var q=class extends E{constructor(){super(...arguments);this.eventHandlers=[];this.capturedEvents=["click","change","keydown","select","submit"];this.getShouldMaskText=e=>[e.target?.type==="password",e.target?.id?.toLowerCase().includes("password"),e.target?.id?.toLowerCase().includes("credit-card"),e.target?.id?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.getAttribute("data-private")].some(n=>n);this.getKeyCode=e=>{if(e instanceof KeyboardEvent&&e.code&&e.key!=="Dead"){let t=this.getShouldMaskText({target:e.target});return t||t?"*":e.key}return ""};this.getText=e=>{let t=e.target;return C({text:t.innerText||""})};this.getSelector=e=>e.target instanceof Element&&this.generateSelector(e.target)||"";this.getCoordinates=e=>{if({mouseup:true,mousedown:true,mousemove:true,mouseover:true}[e.type]){let{clientX:n,clientY:o}=e||{};return {clientX:n,clientY:o}}return null};}initialize(){try{this.logger.log("[dom-events-listener.initialize] called"),this.capturedEvents?.forEach(e=>{let t=n=>{try{this.handleEvent(n);}catch(o){a(o);}};this.eventHandlers.push({type:e,handler:t}),g?.addEventListener(e,t);});}catch(e){a(e);}}destroy(){this.eventHandlers.forEach(({type:e,handler:t})=>{global?.removeEventListener?.(e,t);}),this.eventHandlers=[];}handleEvent(e){try{if(!T())return;let n=this.buildEvent(e);this.queueEvent(n);}catch(t){a(t);}}buildEvent(e){let t=this.getSelector(e),n=this.getCoordinates(e),o=e.target,c=this.getKeyCode(e),s=this.getText(e);this.logger.log("[dom-events-listener.buildEvent] called");let d={dom_event_selector:t,dom_event_key_code:c,dom_event_type:e.type,dom_event_coordinates:n||{clientX:0,clientY:0},dom_event_target:{id:o.id,tagName:o.tagName,className:o.className,text:s}};return f({type:"dom.event",attributes:d})}queueEvent(e){try{this.logger.log("[dom-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}generateSelector(e,t={}){if(!e||!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return "";let n=t.root||document.body||document.documentElement,o=t.maxAttempts||10,c=t.priorityAttributes||["id","class","name","aria-label","type","title","alt"];if(e.tagName?.toLowerCase()==="html")return "html";let s="",d=0,l=e,v=[];for(;l&&l!==n&&l!==document.documentElement&&d<o;){let p=l.tagName?.toLowerCase()||"";try{let h=l.getAttribute("id");if(h&&/^[a-zA-Z][\w-]*$/.test(h))return `#${h}`;if(l.classList?.length){let u=Array.from(l.classList).filter(m=>m&&typeof m=="string").map(m=>`.${m}`);u.length&&(p+=u.join(""));}for(let u of c)if(!(u==="id"||u==="class"))try{let m=l.getAttribute(u);m&&(p+=`[${u}="${m.replace(/"/g,'\\"')}"]`);}catch{}}catch{p=l.tagName?.toLowerCase()||"*";}v.unshift(p||"*"),s=v.join(" > ");try{if(n.querySelectorAll(s).length===1)return s}catch{v.shift(),s=v.join(" > ");}try{l=l.parentElement;}catch{break}d++;}return s||"*"}};var F=["log","info","warn","error","assert","trace"],z=class extends E{constructor(){super(...arguments);this.originalConsole=null;this.isInitialized=false;}initialize(){if(!this.isInitialized)try{this.originalConsole=this.captureConsoleMethods(),F.forEach(e=>{e in console&&(console[e]=(...t)=>{try{this.handleEvent(t,e);}catch(n){a(n);}finally{this.originalConsole?.[e]&&this.originalConsole[e](...t);}});}),this.isInitialized=!0;}catch(e){a(e);}}destroy(){try{if(!this.isInitialized)return;F.forEach(e=>{this.originalConsole&&this.originalConsole[e]&&(console[e]=this.originalConsole[e]);}),this.isInitialized=!1;}catch(e){a(e);}}handleEvent(e,t){try{if(!T())return;let o=this.formatMessage(Array.isArray(e)?e:[e]);if(!o||o?.includes("groundcoverIgnore"))return;let c=this.buildEvent({message:o,level:t});this.queueEvent(c);}catch(n){a(n);}}buildEvent({message:e,level:t}){return f({type:"log",attributes:{message:C({text:e}),level:t}})}queueEvent(e){try{this.logger.log("[logs-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}formatMessage(e){if(!Array.isArray(e))return String(e);try{return e.map(t=>{if(t===void 0)return "undefined";if(t===null)return "null";if(typeof t=="object")try{return JSON.stringify(t)}catch{return Object.prototype.toString.call(t)}return String(t)}).join(" ")}catch(t){return a(t),"[Error formatting console message]"}}captureConsoleMethods(){let e={};try{F.forEach(t=>{console&&typeof console[t]=="function"&&(e[t]=console[t].bind(console));});}catch(t){a(t);}return e}};var M=class extends E{constructor(){super(...arguments);this.config=y.getInstance();this.idGenerator=new L;this.handleEvent=(e,t={})=>{try{let n=this.config.getConfig()?.dsn;if(n&&e.url?.includes(n)||!T())return;let c=this.buildEvent(e,t);this.queueEvent(c);}catch(n){a(n);}};this.buildEvent=(e,t={})=>{let n=e.url,o=e.url;this.logger.log("[network-events-listener.buildEvent] called",{event:e});try{n=new URL(e.url).pathname;}catch{o=new URL(e.url,globalThis.location.href).href;}this.logger.log("[network-events-listener.buildEvent] fullUrl",{fullUrl:o});let c=this.formatHeaders(e.request.headers),s={type:"HTTP",operation:{name:e.method},resource_name:n,status:e.status?.toString(),subType:e.method,http:{url:{full:o},route:n,path:n,method:e.method,status:e.status?.toString(),request:{headers:c,method:e.method},response:{headers:c,status_code:e.status?.toString()}},error:e?.error?.type?{type:e.error?.type||"Unknown error"}:void 0,gc:{request:{body:e.request.body},response:{body:e.response.body}}};return f({type:"network",timestamp:e?.timestamp&&!Number.isNaN(e.timestamp)?e.timestamp*1e6:void 0,end_timestamp:e?.end_time&&!Number.isNaN(e.end_time)?e.end_time*1e6:void 0,span_name:`${e.method} ${n}`,attributes:s,traceId:t?.traceId,spanId:t?.spanId})};}initialize(){this.logger.log("[network-events-listener.initialize] called"),this.patchXHR(),this.patchFetch();}destroy(){globalThis.XMLHttpRequest.prototype.open=globalThis.XMLHttpRequest.prototype.open,globalThis.XMLHttpRequest.prototype.send=globalThis.XMLHttpRequest.prototype.send,globalThis.fetch=globalThis.fetch;}queueEvent(e){try{this.logger.log("[network-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}patchXHR(){let e=this,t=globalThis.XMLHttpRequest.prototype.open,n=globalThis.XMLHttpRequest.prototype.send,o=globalThis.XMLHttpRequest.prototype.setRequestHeader,c,s={traceId:"",spanId:""};globalThis.XMLHttpRequest.prototype.open=function(d,l,v=true,p,h){if(c=Date.now(),e.shouldIgnoreRequest(l.toString()))return t.apply(this,[d,l,v,p,h]);let u=new URL(l.toString(),globalThis.location.href).href;return this._requestMethod=d,this._requestUrl=u,this._requestHeaders={},t.apply(this,[d,l,v,p,h])},globalThis.XMLHttpRequest.prototype.setRequestHeader=function(d,l){return this._requestHeaders&&(this._requestHeaders[d]=l),o.apply(this,[d,l])},globalThis.XMLHttpRequest.prototype.send=function(...d){let l=this._requestUrl.toString();if(!l||e.shouldIgnoreRequest(l))return n.apply(this,d);if(e.shouldAddTraceHeader(l)){let p=e.getTraceparentHeader();s=p,p&&(this.setRequestHeader("traceparent",p.traceparent),this._requestHeaders.traceparent=p.traceparent);}return this._requestBody=d[0]||"",this.addEventListener("load",()=>{let p=Date.now(),h={};this.getAllResponseHeaders().split(/\r?\n/).forEach(m=>{let[I,S]=m.split(": ");I&&S&&(h[I.trim()]=S.trim());});let u={timestamp:c,end_time:p,method:this._requestMethod,url:this._requestUrl,body:this._requestBody,status:this.status,request:{headers:this._requestHeaders||{},body:this._requestBody},response:{headers:h,body:this.responseText||this.response||""}};e.handleEvent(u,{traceId:s.traceId,spanId:s.spanId});}),n.apply(this,d)};}patchFetch(){let e={traceId:"",spanId:""},t=globalThis.fetch;globalThis.fetch=(...n)=>{let o=Date.now(),[c,s={}]=n,d=s?.method||"GET",l=s?.body||"",v=c instanceof Request?c.url:c.toString();if(this.shouldIgnoreRequest(v))return t.apply(globalThis,n);let p=this.shouldAddTraceHeader(v);if(s&&!s.headers&&(s.headers={}),p){let u=this.getTraceparentHeader();e=u,u&&(s?.headers instanceof Headers?s.headers.set("traceparent",u.traceparent):s.headers={...s.headers,traceparent:u.traceparent});}let h={};return s?.headers&&(s.headers instanceof Headers?s.headers.forEach((u,m)=>{h[m]=u;}):typeof s.headers=="object"&&Object.assign(h,s.headers)),t.apply(globalThis,n).then(async u=>{let m=Date.now(),I=u.clone(),S="";try{S=await I.text();}catch{S="[unreadable response body]";}let x={};I.headers.forEach((G,W)=>{x[W]=G;}),this.logger.log("[network-events-listener.patchFetch] called",{url:v});let Y={method:d,url:v,timestamp:o,body:l.toString(),status:I.status,end_time:m,request:{headers:h,body:l.toString()},response:{headers:x,body:S}};return this.handleEvent(Y,{traceId:e.traceId,spanId:e.spanId}),u}).catch(u=>{let m=Date.now(),I="NetworkError",S=u.message||"Unknown network error";u instanceof TypeError&&S.includes("Failed to fetch")?I="ERR_NETWORK_FAILURE":S.includes("Name not resolved")?I="ERR_NAME_NOT_RESOLVED":S.includes("Connection refused")&&(I="ERR_CONNECTION_REFUSED");let x={method:d,url:v,body:l.toString(),status:0,end_time:m,request:{headers:h,body:l.toString()},response:{headers:{},body:""},error:{type:I}};throw this.handleEvent(x,{traceId:e.traceId,spanId:e.spanId}),u})};}formatHeaders(e){let t=["authorization","cookie","set-cookie"];return Object.entries(e)?.reduce((n,[o,c])=>{let s=o.toLowerCase();return t.includes(s)||/(token|key|secret|password)/i.test(s)?n[o]="[REDACTED]":n[o]=C({text:c}),n},{})}shouldIgnoreRequest(e){return [".tsx",".jsx",".css"].some(n=>e.toLowerCase().endsWith(n))}getTraceparentHeader(){let e=this.idGenerator.generateSpanId(),t=this.idGenerator.generateTraceId();return {traceparent:`00-${t}-${e}-01`,traceId:t,spanId:e}}shouldAddTraceHeader(e){let t=this.config.getConfig();if(this.logger.log("[network-events-listener.shouldAddTraceHeader] called",{url:e,config:t}),!t||!t.options.tracePropagationUrls||!t.options.tracePropagationUrls?.length)return false;let n=t.options.tracePropagationUrls.some(o=>{let c=o.replace(/\*/g,".*"),s=new RegExp(`^${c}$`),l=e.startsWith("/")?new URL(e,globalThis.location.href).pathname:e;return s.test(l)});return this.logger.log("[network-events-listener.shouldAddTraceHeader] result",{url:e,result:n}),n}};var P=class extends E{constructor(){super(...arguments);this.handleEvent=(e,t)=>{this.logger.log("[errors-events-listener.handleEvent] called");try{let n;if(e instanceof Error)n=e,this.enhanceError(n);else if(e instanceof ErrorEvent){if(n=e.error||new Error(e.message||"Unknown error"),/Script error\.?/.test(n.message))return;this.enhanceError(n,e);}else if(e instanceof PromiseRejectionEvent)n=this.createUnhandledRejectionError(e);else return;let o=this.buildEvent(n,t);this.queueEvent(o);}catch(n){a(n);}};}initialize(){g?.addEventListener("error",this.handleEvent),g?.addEventListener("unhandledrejection",this.handleEvent);}destroy(){g?.removeEventListener("error",this.handleEvent),g?.removeEventListener("unhandledrejection",this.handleEvent);}buildEvent(e,t){let n={error_type:e.name||"Error",error_message:e.message||"Unknown error",error_stacktrace:this.buildStackTrace(e),error_fingerprint:`${e.name}:${C({text:e.message,maxLength:400})}`,error_handled:t?.handled||false};return f({type:"exception",attributes:n})}queueEvent(e){try{this.logger.log("[errors-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}enhanceError(e,t){let{filename:n,lineno:o,colno:c}=t||{};n&&!e.fileName&&Object.defineProperty(e,"fileName",{value:n}),o&&!e.lineNumber&&Object.defineProperty(e,"lineNumber",{value:o}),c&&!e.columnNumber&&Object.defineProperty(e,"columnNumber",{value:c});}createUnhandledRejectionError(e){let t;if(e.reason instanceof Error)t=e.reason;else {let n=typeof e.reason=="object"?JSON.stringify(e.reason,null,2):String(e.reason);t=new Error(n),t.name="UnhandledRejection",Object.defineProperty(t,"originalReason",{value:e.reason,enumerable:false});}return t}buildStackTrace(e){if(!e)return [];try{return ee.parse(e).map(n=>({filename:n.fileName||"unknown",function:n.functionName||"anonymous",lineno:n.lineNumber||0,colno:n.columnNumber||0}))}catch{return []}}};var D=class extends E{constructor(){super(...arguments);this.currentUrl=globalThis.location.href;this.mutationObserver=null;}initialize(){if(g.MutationObserver){let e=g.document.querySelector("body");e&&(this.mutationObserver=new MutationObserver(()=>{this.handleUrlChange();}),this.mutationObserver.observe(e,{childList:true,subtree:true}));}g?.addEventListener("popstate",()=>{this.handleUrlChange();});}destroy(){this.mutationObserver?.disconnect(),this.mutationObserver=null;}handleEvent(){try{this.logger.log("[navigation-listener.handleEvent] called");let e=this.buildEvent();this.queueEvent(e);}catch(e){a(e);}}buildEvent(){let e={page_url:globalThis.location.href};return f({type:"navigation",attributes:e})}queueEvent(e){try{this.logger.log("[navigation-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}handleUrlChange(){this.logger.log("[navigation-listener.handleUrlChange] called");let e=new URL(globalThis.location.href),t=new URL(this.currentUrl);e.pathname!==t.pathname&&(this.currentUrl=globalThis.location.href,this.handleEvent());}};var H=class extends E{constructor(){super(),this.startTime=performance.now();}initialize(){try{this.logger.log("[page-load-listener.initialize] called"),g?.addEventListener("load",()=>{this.handleEvent();});}catch(r){a(r);}}destroy(){g?.removeEventListener("load",this.handleEvent);}handleEvent(){try{this.logger.log("[page-load-listener.handleEvent] called");let r=this.buildEvent();this.queueEvent(r);}catch(r){a(r);}}buildEvent(){let r=performance.now()-this.startTime,e=performance.getEntriesByType("resource"),t={count:e.length,totalSize:0,totalDuration:0,byType:{}};e.forEach(o=>{let c=o,s=c.transferSize||0,d=c.duration,l=c.initiatorType;t.totalSize+=s,t.totalDuration+=d,t.byType[l]||(t.byType[l]={count:0,size:0,duration:0}),t.byType[l].count++,t.byType[l].size+=s,t.byType[l].duration+=d;});let n={page_url:g?.location?.href||"",page_load_time:r,page_referrer:g?.document?.referrer||"",page_resources:t};return f({type:"pageload",attributes:n})}queueEvent(r){try{this.logger.log("[page-load-listener.queueEvent] called"),r&&this.eventsPool.addEvent(r);}catch(e){a(e);}}};var U=class extends E{constructor(){super(...arguments);this.handleEvent=e=>{try{if(!T())return;let n=this.buildEvent(e);this.queueEvent(n);}catch(t){a(t);}};}initialize(){onCLS(this.handleEvent),onLCP(this.handleEvent),onFCP(this.handleEvent),onTTFB(this.handleEvent),onINP(this.handleEvent);}destroy(){}buildEvent(e){let t={performance_metric_name:e.name,performance_metric_value:e.value,performance_metric_id:e.id,performance_metric_navigation_type:e.navigationType||""};return f({type:"performance",attributes:t})}queueEvent(e){try{this.logger.log("[performance-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e);}catch(t){a(t);}}};var O=class{constructor(){this.logger=b.getInstance();this.eventsPool=w.getInstance();this.logEventsListener=null;this.domEventsListener=null;this.errorsEventsListener=null;this.networkEventsListener=null;this.navigationListener=null;this.performanceListener=null;this.pageLoadListener=null;}instrument(){this.logger.log("[instrumentation-manager.instrument] called"),this.domEventsListener=new q,this.logEventsListener=new z,this.errorsEventsListener=new P,this.networkEventsListener=new M,this.navigationListener=new D,this.performanceListener=new U,this.pageLoadListener=new H,this.domEventsListener.initialize(),this.logEventsListener.initialize(),this.errorsEventsListener.initialize(),this.networkEventsListener.initialize(),this.navigationListener.initialize(),this.performanceListener.initialize(),this.pageLoadListener.initialize(),this.logger.log("[instrumentation-manager.instrument] initialized listeners");}sendCustomEvent(r){this.logger.log("[instrumentation-manager.sendCustomEvent] called",r);try{let e=f({type:"custom",attributes:{custom_event_name:r?.event,custom_user:r?.attributes}});this.eventsPool.addEvent(e);}catch(e){a(e);}}captureException(r){try{this.logger.log("[instrumentation-manager.captureException] called",r),this.errorsEventsListener?.handleEvent(r,{handled:!0});}catch(e){a(e);}}uninstrument(){this.domEventsListener?.destroy(),this.logEventsListener?.destroy(),this.errorsEventsListener?.destroy(),this.networkEventsListener?.destroy(),this.navigationListener?.destroy(),this.performanceListener?.destroy();}};var K=class{constructor(r){this.initialized=false;if(this.logger=b.initialize({debug:r.options?.debug||false,prefix:"[groundcover]"}),this.logger.log("[session-manager] initialize called"),this.instrumentationManager=new O,this.idGenerator=new L,!(r.options?.sessionSampleRate?Math.random()<r.options?.sessionSampleRate:true)){this.logger.log("[session-manager] session is not sampled");return}if(this.initialized){this.logger.log("[session-manager] SDK already initialized");return}let t=y.getInstance();t.initialize(r),w.getInstance().initialize(),t.getSessionId()||t.setSessionId(this.idGenerator.generateId()),this.instrumentationManager.instrument(),this.initialized=true;}identifyUser(r){if(this.logger.log("[session-manager] identifyUser called"),!this.initialized){this.logger.log("[session-manager] cannot identify user: SDK not initialized");return}y.getInstance().updateConfig({userIdentifier:r});}sendCustomEvent(r){if(!this.initialized){this.logger.log("[session-manager] cannot send custom event: SDK not initialized");return}this.instrumentationManager.sendCustomEvent(r);}captureException(r){if(!this.initialized){this.logger.log("[session-manager] Cannot capture exception: SDK not initialized");return}this.instrumentationManager.captureException(r);}destroy(){this.initialized&&(this.instrumentationManager.uninstrument(),globalThis.sessionStorage?.removeItem("gcId"),this.initialized=false);}};var _;function se(i){try{_=new K({cluster:i?.cluster,environment:i?.environment,dsn:i?.dsn,appId:i?.appId,userIdentifier:i?.userIdentifier,apiKey:i?.apiKey,options:i?.options});}catch(r){a(r);}}function ae(i){if(!_){console.warn("[groundcover] identifyUser: groundcover is not initialized. please call init() first");return}_.identifyUser(i);}function le(i){_&&_.sendCustomEvent(i);}function ce(i){_&&_.captureException(i);}var Gt={init:se,identifyUser:ae,sendCustomEvent:le,captureException:ce};export{Gt as default};
1
+ import e from"error-stack-parser";import{onCLS as t,onLCP as n,onFCP as s,onTTFB as i,onINP as r}from"web-vitals";var o=console.log.bind(console),a=class e{constructor(){this.isDebugEnabled=!1,this.prefix=""}static initialize(t){return e.instance||(e.instance=new e),t&&(e.instance.isDebugEnabled=t.debug??!1,e.instance.prefix=t.prefix??""),e.instance}static getInstance(t){return e?.instance||e.initialize(t)}formatMessage(e){return`[${(new Date).toISOString()}] ${this.prefix} ${e}`}log(e,...t){this.isDebugEnabled&&o(this.formatMessage(e),...t)}updateConfig(e){this.isDebugEnabled=e.debug??this.isDebugEnabled,this.prefix=e.prefix??this.prefix}},l=a.getInstance();function c(e){l.log("[error-handler.handleError] called",e,{groundcoverIgnore:!0})}var h={batchSize:10,batchTimeout:1e4,eventSampleRate:1,sessionSampleRate:1,environment:"development",debug:!1,maskFields:[],enabledEvents:["dom","network","error","log"],tracePropagationUrls:[]},d=class{constructor(e){this.dsn=e.dsn,this.appId=e.appId,this.cluster=e.cluster,this.apiKey=e.apiKey,this.environment=e.environment,this.userIdentifier=e.userIdentifier||null,this.options={...h,...e.options}}getEndpoint(){return this.dsn}},u=class{constructor(){this.generateTraceId=p(16),this.generateSpanId=p(8),this.generateId=p(16)}},g=Array(32);function p(e){return function(){for(let t=0;t<2*e;t++)g[t]=Math.floor(16*Math.random())+48,g[t]>=58&&(g[t]+=39);return String.fromCharCode.apply(null,g.slice(0,2*e))}}var m=class e{constructor(){this.config=null,this.logger=a.getInstance(),this.sessionId=null,this.idGenerator=new u}static getInstance(){return e.instance||(e.instance=new e),e.instance}initialize(e){this.config||(this.config=new d(e))}getConfig(){return this.config?this.config:(this.logger.log("[config-manager] configuration not initialized"),null)}getSessionId(){if(this.sessionId)return this.sessionId;const e=globalThis?.sessionStorage?.getItem("gcId");return e||""}setSessionId(e){this.sessionId=e,globalThis?.sessionStorage?.setItem("gcId",e)}updateConfig(e){this.logger.log("[config-manager] updateConfig called"),this.config?(e?.options&&(this.logger.log("[config-manager] updating options"),this.config.options={...this.config.options,...e.options}),e?.userIdentifier&&(this.logger.log("[config-manager] updating user identifier"),this.config.userIdentifier={...this.config.userIdentifier,...e.userIdentifier})):this.logger.log("[config-manager] configuration not initialized")}},f="object"==typeof globalThis?globalThis:"object"==typeof self?self:"object"==typeof window?window:"object"==typeof global?global:{},v=m.getInstance(),y=new u;function E(){const e=v?.getConfig()?.options?.eventSampleRate;return!(void 0!==e&&!Number.isNaN(e))||Math.random()<=e}function b(e,t=""){return Object.entries(e).reduce(((e,[n,s])=>{const i=t?`${t}.${n}`:n;return"object"==typeof s&&null!==s?Object.assign(e,b(s,i)):e[i]=s,e}),{})}function I(e){const t=1e6*Date.now(),n=y.generateId(),s=e.spanId||y.generateSpanId(),i=e.traceId||y.generateTraceId(),r=e.parentSpanId||"",o=b(e.attributes||{}),a={path:f?.location?.pathname,url:f?.location?.href,title:f?.document?.title},l={type:e.type,id:n,spanId:s,parentSpanId:r,traceId:i,attributes:{...o,location:a}};return e.span_name&&(l.span_name=e.span_name),"network"===e.type?(l.start_timestamp=e.timestamp||t,l.end_timestamp=e?.end_timestamp):l.timestamp=t,l}var w=class{constructor(){this.logger=a.getInstance(),this.config=m.getInstance()}async send(e){const t=this.config.getConfig();if(t)try{if(t.options.debug)return void this.logger.log("Sending batch:",e,{groundcoverIgnore:!0});const n=t.apiKey,s=this.buildEndpoint();if(!n)return void this.logger.log("No API key found");fetch(s,{method:"POST",headers:{"Content-Type":"application/json",apikey:n},body:JSON.stringify(e)})}catch(e){t.options.debug&&this.logger.log("Failed to send batch:",e,{groundcoverIgnore:!0})}}buildEndpoint(){const e=this.config.getConfig();if(!e)return"";const{dsn:t}=e;return`${t}/json/rum`}},T=class e{constructor(){this.events=[],this.timeoutId=null,this.config=m.getInstance(),this.initialized=!1,this.transporter=new w}static getInstance(){return e.instance||(e.instance=new e),e.instance}initialize(){try{if(this.initialized)return;this.scheduleFlush(),globalThis.addEventListener("unload",(()=>{this.flush()})),this.initialized=!0}catch(e){c(e)}}addEvent(e){if(!e||!this.initialized)return;this.events.push(e);const t=this.config.getConfig()?.options?.batchSize||100;this.events.length>=t&&this.flush()}flush(){try{if(0===this.events.length||!this.initialized)return;this.transporter.send({sessionAttributes:this.getSessionAttributes(),events:this.events}),this.events=[],this.scheduleFlush()}catch(e){c(e)}}scheduleFlush(){try{null!==this.timeoutId&&(f.clearTimeout(this.timeoutId),this.timeoutId=null);const e=this.config.getConfig()?.options?.batchTimeout;if(!e)return;this.timeoutId=f.setTimeout((()=>{this.timeoutId=null,this.flush()}),e)}catch(e){c(e)}}detectBrowser(){const e=navigator.userAgent;let t="unknown",n="unknown";const s=navigator.platform||"unknown",i=/Mobile|Android|iPhone|iPad|iPod/i.test(e);return/Edg/.test(e)?(t="Edge",n=e.match(/Edg\/([\d.]+)/)?.[1]||n):/Chrome/.test(e)&&!/Chromium/.test(e)?(t="Chrome",n=e.match(/Chrome\/([\d.]+)/)?.[1]||n):/Firefox/.test(e)?(t="Firefox",n=e.match(/Firefox\/([\d.]+)/)?.[1]||n):/Safari/.test(e)&&!/Chrome/.test(e)?(t="Safari",n=e.match(/Version\/([\d.]+)/)?.[1]||n):/Trident/.test(e)?(t="Internet Explorer",n=/rv:([^)]+)\)/i.test(e)?e.match(/rv:([^)]+)\)/i)?.[1]||n:e.match(/MSIE ([^;]+)/)?.[1]||n):/OPR/.test(e)&&(t="Opera",n=e.match(/OPR\/([\d.]+)/)?.[1]||n),{name:t,version:n,platform:s,language:navigator.language,mobile:i}}getSessionAttributes(){const e=this.detectBrowser();return{cluster:this.config.getConfig()?.cluster||"",env:this.config.getConfig()?.environment||"",session_id:this.config.getSessionId(),user:this.config.getConfig()?.userIdentifier||{},"service.name":this.config.getConfig()?.appId,userAgent:navigator.userAgent,browser:e}}};T.instance=null;var L=T,_=class{constructor(){this.logger=a.getInstance(),this.eventsPool=L.getInstance()}};function S({text:e,maxLength:t=1e4}){return e?e.length<=t||"string"!=typeof e?e:e.substring(0,t):""}var C,q=class extends _{constructor(){super(...arguments),this.eventHandlers=[],this.capturedEvents=["click","change","keydown","select","submit"],this.getShouldMaskText=e=>["password"===e.target?.type,e.target?.id?.toLowerCase().includes("password"),e.target?.id?.toLowerCase().includes("credit-card"),e.target?.id?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("cc"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.className?.toLowerCase().includes("credit-card"),e.target?.getAttribute("data-private")].some((e=>e)),this.getKeyCode=e=>{if(e instanceof KeyboardEvent&&e.code&&"Dead"!==e.key){const t=this.getShouldMaskText({target:e.target});return t||t?"*":e.key}return""},this.getText=e=>S({text:e.target.innerText||""}),this.getSelector=e=>e.target instanceof Element&&this.generateSelector(e.target)||"",this.getCoordinates=e=>{if({mouseup:!0,mousedown:!0,mousemove:!0,mouseover:!0}[e.type]){const{clientX:t,clientY:n}=e||{};return{clientX:t,clientY:n}}return null}}initialize(){try{this.logger.log("[dom-events-listener.initialize] called"),this.capturedEvents?.forEach((e=>{const t=e=>{try{this.handleEvent(e)}catch(e){c(e)}};this.eventHandlers.push({type:e,handler:t}),f?.addEventListener(e,t)}))}catch(e){c(e)}}destroy(){this.eventHandlers.forEach((({type:e,handler:t})=>{global?.removeEventListener?.(e,t)})),this.eventHandlers=[]}handleEvent(e){try{if(!E())return;const t=this.buildEvent(e);this.queueEvent(t)}catch(e){c(e)}}buildEvent(e){const t=this.getSelector(e),n=this.getCoordinates(e),s=e.target,i=this.getKeyCode(e),r=this.getText(e);this.logger.log("[dom-events-listener.buildEvent] called");return I({type:"dom.event",attributes:{dom_event_selector:t,dom_event_key_code:i,dom_event_type:e.type,dom_event_coordinates:n||{clientX:0,clientY:0},dom_event_target:{id:s.id,tagName:s.tagName,className:s.className,text:r}}})}queueEvent(e){try{this.logger.log("[dom-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}generateSelector(e,t={}){if(!e||!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return"";const n=t.root||document.body||document.documentElement,s=t.maxAttempts||10,i=t.priorityAttributes||["id","class","name","aria-label","type","title","alt"];if("html"===e.tagName?.toLowerCase())return"html";let r="",o=0,a=e;const l=[];for(;a&&a!==n&&a!==document.documentElement&&o<s;){let e=a.tagName?.toLowerCase()||"";try{const t=a.getAttribute("id");if(t&&/^[a-zA-Z][\w-]*$/.test(t))return`#${t}`;if(a.classList?.length){const t=Array.from(a.classList).filter((e=>e&&"string"==typeof e)).map((e=>`.${e}`));t.length&&(e+=t.join(""))}for(const t of i)if("id"!==t&&"class"!==t)try{const n=a.getAttribute(t);n&&(e+=`[${t}="${n.replace(/"/g,'\\"')}"]`)}catch(e){}}catch(t){e=a.tagName?.toLowerCase()||"*"}l.unshift(e||"*"),r=l.join(" > ");try{if(1===n.querySelectorAll(r).length)return r}catch(e){l.shift(),r=l.join(" > ")}try{a=a.parentElement}catch(e){break}o++}return r||"*"}},z=["log","info","warn","error","assert","trace"],R=class extends _{constructor(){super(...arguments),this.originalConsole=null,this.isInitialized=!1}initialize(){if(!this.isInitialized)try{this.originalConsole=this.captureConsoleMethods(),z.forEach((e=>{e in console&&(console[e]=(...t)=>{try{this.handleEvent(t,e)}catch(e){c(e)}finally{this.originalConsole?.[e]&&this.originalConsole[e](...t)}})})),this.isInitialized=!0}catch(e){c(e)}}destroy(){try{if(!this.isInitialized)return;z.forEach((e=>{this.originalConsole&&this.originalConsole[e]&&(console[e]=this.originalConsole[e])})),this.isInitialized=!1}catch(e){c(e)}}handleEvent(e,t){try{if(!E())return;const n=this.formatMessage(Array.isArray(e)?e:[e]);if(!n||n?.includes("groundcoverIgnore"))return;const s=this.buildEvent({message:n,level:t});this.queueEvent(s)}catch(e){c(e)}}buildEvent({message:e,level:t}){return I({type:"log",attributes:{message:S({text:e}),level:t}})}queueEvent(e){try{this.logger.log("[logs-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}formatMessage(e){if(!Array.isArray(e))return String(e);try{return e.map((e=>{if(void 0===e)return"undefined";if(null===e)return"null";if("object"==typeof e)try{return JSON.stringify(e)}catch{return Object.prototype.toString.call(e)}return String(e)})).join(" ")}catch(e){return c(e),"[Error formatting console message]"}}captureConsoleMethods(){const e={};try{z.forEach((t=>{console&&"function"==typeof console[t]&&(e[t]=console[t].bind(console))}))}catch(e){c(e)}return e}},x=class extends _{constructor(){super(...arguments),this.config=m.getInstance(),this.idGenerator=new u,this.handleEvent=e=>{try{const t=this.config.getConfig()?.dsn;if(t&&e.url?.includes(t))return;if(!E())return;const n=this.buildEvent(e);this.queueEvent(n)}catch(e){c(e)}},this.buildEvent=e=>{let t=e.url,n=e.url;this.logger.log("[network-events-listener.buildEvent] called",{event:e});try{t=new URL(e.url).pathname}catch(t){n=new URL(e.url,globalThis.location.href).href}this.logger.log("[network-events-listener.buildEvent] fullUrl",{fullUrl:n});const s=this.formatHeaders(e.request.headers),i=e.request.headers.traceparent,r=i?.split("-")?.[1]||"",o=i?.split("-")?.[2]||"",a={type:"HTTP",operation:{name:e.method},resource_name:t,status:e.status?.toString(),subType:e.method,http:{url:{full:n},route:t,path:t,method:e.method,status:e.status?.toString(),request:{headers:s,method:e.method},response:{headers:s,status_code:e.status?.toString()}},error:e?.error?.type?{type:e.error?.type||"Unknown error"}:void 0,gc:{request:{body:e.request.body},response:{body:e.response.body}}};return I({type:"network",timestamp:e?.timestamp&&!Number.isNaN(e.timestamp)?1e6*e.timestamp:void 0,end_timestamp:e?.end_time&&!Number.isNaN(e.end_time)?1e6*e.end_time:void 0,span_name:`${e.method} ${t}`,attributes:a,traceId:r,spanId:o})}}initialize(){this.logger.log("[network-events-listener.initialize] called"),this.patchXHR(),this.patchFetch()}destroy(){globalThis.XMLHttpRequest.prototype.open=globalThis.XMLHttpRequest.prototype.open,globalThis.XMLHttpRequest.prototype.send=globalThis.XMLHttpRequest.prototype.send,globalThis.fetch=globalThis.fetch}queueEvent(e){try{this.logger.log("[network-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}patchXHR(){const e=this,t=globalThis.XMLHttpRequest.prototype.open,n=globalThis.XMLHttpRequest.prototype.send,s=globalThis.XMLHttpRequest.prototype.setRequestHeader;let i;globalThis.XMLHttpRequest.prototype.open=function(n,s,r=!0,o,a){if(i=Date.now(),e.shouldIgnoreRequest(s.toString()))return t.apply(this,[n,s,r,o,a]);const l=new URL(s.toString(),globalThis.location.href).href;return this._requestMethod=n,this._requestUrl=l,this._requestHeaders={},t.apply(this,[n,s,r,o,a])},globalThis.XMLHttpRequest.prototype.setRequestHeader=function(e,t){return this._requestHeaders&&(this._requestHeaders[e]=t),s.apply(this,[e,t])},globalThis.XMLHttpRequest.prototype.send=function(...t){const s=this._requestUrl.toString();if(!s||e.shouldIgnoreRequest(s))return n.apply(this,t);if(e.shouldAddTraceHeader(s)){const t=e.getTraceparentHeader();t&&(this.setRequestHeader("traceparent",t.traceparent),this._requestHeaders.traceparent=t.traceparent)}return this._requestBody=t[0]||"",this.addEventListener("load",(()=>{const t=Date.now(),n={};this.getAllResponseHeaders().split(/\r?\n/).forEach((e=>{const[t,s]=e.split(": ");t&&s&&(n[t.trim()]=s.trim())}));const s={timestamp:i,end_time:t,method:this._requestMethod,url:this._requestUrl,body:this._requestBody,status:this.status,request:{headers:this._requestHeaders||{},body:this._requestBody},response:{headers:n,body:this.responseText||this.response||""}};e.handleEvent(s)})),n.apply(this,t)}}patchFetch(){const e=globalThis.fetch;globalThis.fetch=(...t)=>{const n=Date.now();let[s,i]=t;i={...i||{}};const r=i?.method||"GET",o=i?.body||"",a=s instanceof Request?s.url:s.toString();if(this.shouldIgnoreRequest(a))return e.apply(globalThis,t);const l=this.shouldAddTraceHeader(a);if(i&&!i.headers&&(i.headers={}),i||(t[1]={},i=t[1]),l){const e=this.getTraceparentHeader();e&&(i?.headers instanceof Headers?i.headers.set("traceparent",e.traceparent):i.headers={...i.headers,traceparent:e.traceparent})}const c={};return i?.headers&&(i.headers instanceof Headers?i.headers.forEach(((e,t)=>{c[t]=e})):"object"==typeof i.headers&&Object.assign(c,i.headers)),e.apply(globalThis,t).then((async e=>{const t=Date.now(),s=e.clone();let i="";try{i=await s.text()}catch(e){i="[unreadable response body]"}const l={};s.headers.forEach(((e,t)=>{l[t]=e})),this.logger.log("[network-events-listener.patchFetch] called",{url:a});const h={method:r,url:a,timestamp:n,body:o.toString(),status:s.status,end_time:t,request:{headers:c,body:o.toString()},response:{headers:l,body:i}};return this.handleEvent(h),e})).catch((e=>{const t=Date.now();let n="NetworkError";const s=e.message||"Unknown network error";e instanceof TypeError&&s.includes("Failed to fetch")?n="ERR_NETWORK_FAILURE":s.includes("Name not resolved")?n="ERR_NAME_NOT_RESOLVED":s.includes("Connection refused")&&(n="ERR_CONNECTION_REFUSED");const i={method:r,url:a,body:o.toString(),status:0,end_time:t,request:{headers:c,body:o.toString()},response:{headers:{},body:""},error:{type:n}};throw this.handleEvent(i),e}))}}formatHeaders(e){const t=["authorization","cookie","set-cookie"];return Object.entries(e)?.reduce(((e,[n,s])=>{const i=n.toLowerCase();return t.includes(i)||/(token|key|secret|password)/i.test(i)?e[n]="[REDACTED]":e[n]=S({text:s}),e}),{})}shouldIgnoreRequest(e){return[".tsx",".jsx",".css"].some((t=>e.toLowerCase().endsWith(t)))}getTraceparentHeader(){const e=this.idGenerator.generateSpanId(),t=this.idGenerator.generateTraceId();return{traceparent:`00-${t}-${e}-01`,traceId:t,spanId:e}}shouldAddTraceHeader(e){const t=this.config.getConfig();if(this.logger.log("[network-events-listener.shouldAddTraceHeader] called",{url:e,config:t}),!t||!t.options.tracePropagationUrls||!t.options.tracePropagationUrls?.length)return!1;const n=t.options.tracePropagationUrls.some((t=>{const n=t.replace(/\*/g,".*"),s=new RegExp(`^${n}$`),i=e.startsWith("/")?new URL(e,globalThis.location.href).pathname:e;return s.test(i)}));return this.logger.log("[network-events-listener.shouldAddTraceHeader] result",{url:e,result:n}),n}},N=class extends _{constructor(){super(...arguments),this.handleEvent=(e,t)=>{this.logger.log("[errors-events-listener.handleEvent] called");try{let n;if(e instanceof Error)n=e,this.enhanceError(n);else if(e instanceof ErrorEvent){if(n=e.error||new Error(e.message||"Unknown error"),/Script error\.?/.test(n.message))return;this.enhanceError(n,e)}else{if(!(e instanceof PromiseRejectionEvent))return;n=this.createUnhandledRejectionError(e)}const s=this.buildEvent(n,t);this.queueEvent(s)}catch(e){c(e)}}}initialize(){f?.addEventListener("error",this.handleEvent),f?.addEventListener("unhandledrejection",this.handleEvent)}destroy(){f?.removeEventListener("error",this.handleEvent),f?.removeEventListener("unhandledrejection",this.handleEvent)}buildEvent(e,t){return I({type:"exception",attributes:{error_type:e.name||"Error",error_message:e.message||"Unknown error",error_stacktrace:this.buildStackTrace(e),error_fingerprint:`${e.name}:${S({text:e.message,maxLength:400})}`,error_handled:t?.handled||!1}})}queueEvent(e){try{this.logger.log("[errors-events-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}enhanceError(e,t){const{filename:n,lineno:s,colno:i}=t||{};n&&!e.fileName&&Object.defineProperty(e,"fileName",{value:n}),s&&!e.lineNumber&&Object.defineProperty(e,"lineNumber",{value:s}),i&&!e.columnNumber&&Object.defineProperty(e,"columnNumber",{value:i})}createUnhandledRejectionError(e){let t;if(e.reason instanceof Error)t=e.reason;else{const n="object"==typeof e.reason?JSON.stringify(e.reason,null,2):String(e.reason);t=new Error(n),t.name="UnhandledRejection",Object.defineProperty(t,"originalReason",{value:e.reason,enumerable:!1})}return t}buildStackTrace(t){if(!t)return[];try{return e.parse(t).map((e=>({filename:e.fileName||"unknown",function:e.functionName||"anonymous",lineno:e.lineNumber||0,colno:e.columnNumber||0})))}catch(e){return[]}}},k=class extends _{constructor(){super(...arguments),this.currentUrl=globalThis.location.href,this.mutationObserver=null}initialize(){if(f.MutationObserver){const e=f.document.querySelector("body");e&&(this.mutationObserver=new MutationObserver((()=>{this.handleUrlChange()})),this.mutationObserver.observe(e,{childList:!0,subtree:!0}))}f?.addEventListener("popstate",(()=>{this.handleUrlChange()}))}destroy(){this.mutationObserver?.disconnect(),this.mutationObserver=null}handleEvent(){try{this.logger.log("[navigation-listener.handleEvent] called");const e=this.buildEvent();this.queueEvent(e)}catch(e){c(e)}}buildEvent(){return I({type:"navigation",attributes:{page_url:globalThis.location.href}})}queueEvent(e){try{this.logger.log("[navigation-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}handleUrlChange(){this.logger.log("[navigation-listener.handleUrlChange] called");const e=new URL(globalThis.location.href),t=new URL(this.currentUrl);e.pathname!==t.pathname&&(this.currentUrl=globalThis.location.href,this.handleEvent())}},H=class extends _{constructor(){super(),this.startTime=performance.now()}initialize(){try{this.logger.log("[page-load-listener.initialize] called"),f?.addEventListener("load",(()=>{this.handleEvent()}))}catch(e){c(e)}}destroy(){f?.removeEventListener("load",this.handleEvent)}handleEvent(){try{this.logger.log("[page-load-listener.handleEvent] called");const e=this.buildEvent();this.queueEvent(e)}catch(e){c(e)}}buildEvent(){const e=performance.now()-this.startTime,t=performance.getEntriesByType("resource"),n={count:t.length,totalSize:0,totalDuration:0,byType:{}};t.forEach((e=>{const t=e,s=t.transferSize||0,i=t.duration,r=t.initiatorType;n.totalSize+=s,n.totalDuration+=i,n.byType[r]||(n.byType[r]={count:0,size:0,duration:0}),n.byType[r].count++,n.byType[r].size+=s,n.byType[r].duration+=i}));return I({type:"pageload",attributes:{page_url:f?.location?.href||"",page_load_time:e,page_referrer:f?.document?.referrer||"",page_resources:n}})}queueEvent(e){try{this.logger.log("[page-load-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}},U=class extends _{constructor(){super(...arguments),this.handleEvent=e=>{try{if(!E())return;const t=this.buildEvent(e);this.queueEvent(t)}catch(e){c(e)}}}initialize(){t(this.handleEvent),n(this.handleEvent),s(this.handleEvent),i(this.handleEvent),r(this.handleEvent)}destroy(){}buildEvent(e){return I({type:"performance",attributes:{performance_metric_name:e.name,performance_metric_value:e.value,performance_metric_id:e.id,performance_metric_navigation_type:e.navigationType||""}})}queueEvent(e){try{this.logger.log("[performance-listener.queueEvent] called"),e&&this.eventsPool.addEvent(e)}catch(e){c(e)}}},M=class{constructor(){this.logger=a.getInstance(),this.eventsPool=L.getInstance(),this.logEventsListener=null,this.domEventsListener=null,this.errorsEventsListener=null,this.networkEventsListener=null,this.navigationListener=null,this.performanceListener=null,this.pageLoadListener=null}instrument(){this.logger.log("[instrumentation-manager.instrument] called"),this.domEventsListener=new q,this.logEventsListener=new R,this.errorsEventsListener=new N,this.networkEventsListener=new x,this.navigationListener=new k,this.performanceListener=new U,this.pageLoadListener=new H,this.domEventsListener.initialize(),this.logEventsListener.initialize(),this.errorsEventsListener.initialize(),this.networkEventsListener.initialize(),this.navigationListener.initialize(),this.performanceListener.initialize(),this.pageLoadListener.initialize(),this.logger.log("[instrumentation-manager.instrument] initialized listeners")}sendCustomEvent(e){this.logger.log("[instrumentation-manager.sendCustomEvent] called",e);try{const t=I({type:"custom",attributes:{custom_event_name:e?.event,custom_user:e?.attributes}});this.eventsPool.addEvent(t)}catch(e){c(e)}}captureException(e){try{this.logger.log("[instrumentation-manager.captureException] called",e),this.errorsEventsListener?.handleEvent(e,{handled:!0})}catch(e){c(e)}}uninstrument(){this.domEventsListener?.destroy(),this.logEventsListener?.destroy(),this.errorsEventsListener?.destroy(),this.networkEventsListener?.destroy(),this.navigationListener?.destroy(),this.performanceListener?.destroy()}},j=class{constructor(e){this.initialized=!1,this.logger=a.initialize({debug:e.options?.debug||!1,prefix:"[groundcover]"}),this.logger.log("[session-manager] initialize called"),this.instrumentationManager=new M,this.idGenerator=new u;if(!(!e.options?.sessionSampleRate||Math.random()<e.options?.sessionSampleRate))return void this.logger.log("[session-manager] session is not sampled");if(this.initialized)return void this.logger.log("[session-manager] SDK already initialized");const t=m.getInstance();t.initialize(e);L.getInstance().initialize();t.getSessionId()||t.setSessionId(this.idGenerator.generateId()),this.instrumentationManager.instrument(),this.initialized=!0}identifyUser(e){if(this.logger.log("[session-manager] identifyUser called"),!this.initialized)return void this.logger.log("[session-manager] cannot identify user: SDK not initialized");m.getInstance().updateConfig({userIdentifier:e})}sendCustomEvent(e){this.initialized?this.instrumentationManager.sendCustomEvent(e):this.logger.log("[session-manager] cannot send custom event: SDK not initialized")}captureException(e){this.initialized?this.instrumentationManager.captureException(e):this.logger.log("[session-manager] Cannot capture exception: SDK not initialized")}destroy(){this.initialized&&(this.instrumentationManager.uninstrument(),globalThis.sessionStorage?.removeItem("gcId"),this.initialized=!1)}};var A={init:function(e){try{C=new j({cluster:e?.cluster,environment:e?.environment,dsn:e?.dsn,appId:e?.appId,userIdentifier:e?.userIdentifier,apiKey:e?.apiKey,options:e?.options})}catch(e){c(e)}},identifyUser:function(e){C?C.identifyUser(e):console.warn("[groundcover] identifyUser: groundcover is not initialized. please call init() first")},sendCustomEvent:function(e){C&&C.sendCustomEvent(e)},captureException:function(e){C&&C.captureException(e)}};export{A as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groundcover/browser",
3
- "version": "0.0.20",
3
+ "version": "0.0.22",
4
4
  "description": "groundcover browser SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -21,7 +21,7 @@
21
21
  "scripts": {
22
22
  "build:local": "tsc --noEmit && tsup",
23
23
  "build:watch": "tsc --noEmit && WATCH=true tsup --watch",
24
- "build:prod": "tsc --noEmit && tsup --minify",
24
+ "build:prod": "tsc --noEmit && tsup",
25
25
  "size": "npm run build:prod && size-limit",
26
26
  "lint": "eslint .",
27
27
  "test": "vitest && npm run lint && npm run size",