scout-error 0.2.2 → 0.2.3

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.cjs CHANGED
@@ -1,5 +1,5 @@
1
- var S=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var U=(e,o)=>{for(var s in o)S(e,s,{get:o[s],enumerable:!0})},D=(e,o,s,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of x(o))!P.call(e,r)&&r!==s&&S(e,r,{get:()=>o[r],enumerable:!(a=L(o,r))||a.enumerable});return e};var A=e=>D(S({},"__esModule",{value:!0}),e);var z={};U(z,{addBreadcrumb:()=>W,captureError:()=>T,init:()=>q,setContext:()=>C,setTag:()=>M,setUser:()=>R});module.exports=A(z);var O={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},n={...O},c={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},E={clicks:0,scrolls:0},b=null,_=!1,g=null,p={},y=[],H=30;var w=console.warn;var I=console.log;function k(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function $(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",k("user")),localStorage.getItem("__scoutUserId")),o=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",k("session")),sessionStorage.getItem("__scoutSessionId"));return b=b||k("pageload"),{pageloadId:b,userId:e,sessionId:o}}function j(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(s=>e.match(s.p))?.n||"Unknown"}function B(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(s=>e.match(s.p))?.n||"Unknown"}function F(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:j(),browserVersion:window._uaParserResult?.browser?.version||null,os:B(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:E.clicks,userScrolls:E.scrolls}}function h(e){return!n.ignoreErrors||!Array.isArray(n.ignoreErrors)?!1:n.ignoreErrors.some(o=>typeof o=="string"?e.includes(o):o instanceof RegExp?o.test(e):!1)}function N(e,o){let s=new AbortController,a=setTimeout(()=>s.abort(),5e3),r={"Content-Type":"application/json"};return n.token&&(r["X-Ingest-Token"]=n.token),fetch(e,{method:"POST",headers:r,body:JSON.stringify(o),signal:s.signal}).then(t=>(clearTimeout(a),t)).catch(()=>{clearTimeout(a)})}function v(e){let o=(e[0]||"")+"",s=[...e];return o.replace(/%[sdj]/g,a=>{let r=s.shift();return a==="%s"?String(r):a==="%d"?Number(r):a==="%j"?JSON.stringify(r):a})}function l(e){y.push({timestamp:Date.now(),...e}),y.length>H&&y.shift()}async function f(e){let o=n.browserDetails?F():{},s=Object.assign(e,o,c,$());if(g&&(s.user=g),Object.keys(p).length&&(s.context={...p}),s.breadcrumbs=y.slice(),n.sampleRate&&Math.random()<1-parseFloat(n.sampleRate)){n.debug&&I("[Scout] Suppressed by sampling");return}if(n.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let a=e.errorTrace.split(`
1
+ var S=Object.defineProperty;var L=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var P=Object.prototype.hasOwnProperty;var U=(e,o)=>{for(var s in o)S(e,s,{get:o[s],enumerable:!0})},D=(e,o,s,a)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of x(o))!P.call(e,r)&&r!==s&&S(e,r,{get:()=>o[r],enumerable:!(a=L(o,r))||a.enumerable});return e};var A=e=>D(S({},"__esModule",{value:!0}),e);var q={};U(q,{addBreadcrumb:()=>W,captureError:()=>T,init:()=>V,setContext:()=>C,setTag:()=>M,setUser:()=>R});module.exports=A(q);var O={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},n={...O},c={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},y={clicks:0,scrolls:0},_=null,b=!1,g=null,p={},E=[],H=30;var w=console.warn;var I=console.log;function k(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function N(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",k("user")),localStorage.getItem("__scoutUserId")),o=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",k("session")),sessionStorage.getItem("__scoutSessionId"));return _=_||k("pageload"),{pageloadId:_,userId:e,sessionId:o}}function $(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(s=>e.match(s.p))?.n||"Unknown"}function j(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(s=>e.match(s.p))?.n||"Unknown"}function B(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:$(),browserVersion:window._uaParserResult?.browser?.version||null,os:j(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:y.clicks,userScrolls:y.scrolls}}function h(e){return!n.ignoreErrors||!Array.isArray(n.ignoreErrors)?!1:n.ignoreErrors.some(o=>typeof o=="string"?e.includes(o):o instanceof RegExp?o.test(e):!1)}function F(e,o){let s=new AbortController,a=setTimeout(()=>s.abort(),5e3),r={"Content-Type":"application/json"};return n.token&&(r["X-Ingest-Token"]=n.token),fetch(e,{method:"POST",headers:r,body:JSON.stringify(o),signal:s.signal}).then(t=>(clearTimeout(a),t)).catch(()=>{clearTimeout(a)})}function v(e){let o=(e[0]||"")+"",s=[...e];return o.replace(/%[sdj]/g,a=>{let r=s.shift();return a==="%s"?String(r):a==="%d"?Number(r):a==="%j"?JSON.stringify(r):a})}function l(e){E.push({timestamp:Date.now(),...e}),E.length>H&&E.shift()}async function f(e){let o=n.browserDetails?B():{},s=Object.assign(e,o,c,N());if(g&&(s.user=g),Object.keys(p).length&&(s.context={...p}),s.breadcrumbs=E.slice(),n.sampleRate&&Math.random()<1-parseFloat(n.sampleRate)){n.debug&&I("[Scout] Suppressed by sampling");return}if(n.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let a=e.errorTrace.split(`
2
2
  `),r=[a[0]];for(let t=1;t<a.length;t++)!a[t].includes("/scout")&&!a[t].includes("scout.js")&&!a[t].includes("scout-error")&&r.push(a[t]);r.length>1&&(e.errorTrace=r.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let a=e.errorTrace||e.stack,r=a?a.split(`
4
- `):[];for(let t=1;t<r.length;t++){let i=r[t].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}n.debug&&I("[Scout] Sending:",s),n.endpoint&&N(n.endpoint,s)}function T(e){n.enabled&&f(e)}function R(e){g=e}function C(e){p={...p,...e}}function M(e,o){p[e]=o}function W(e){l(e)}function X(){if(n.trackUserInteractions){document.addEventListener("click",t=>{E.clicks++;let i=t.target,m=i.tagName?i.tagName.toLowerCase():"",u=(i.textContent||"").trim().slice(0,50);l({category:"click",message:m+(u?": "+u:"")})});let r=0;window.addEventListener("scroll",()=>{let t=Date.now();t-r>100&&(E.scrolls++,r=t)})}let e=history.pushState;history.pushState=function(){e.apply(this,arguments),l({category:"navigation",message:window.location.href})},window.addEventListener("popstate",()=>{l({category:"navigation",message:window.location.href})});let o=window.fetch;window.fetch=function(r,t){let i=typeof r=="string"?r:r?.url||"",m=t?.method||"GET",u=Date.now();return o.apply(this,arguments).then(d=>(l({category:"fetch",message:`${m} ${i}`,data:{status:d.status,duration:Date.now()-u}}),d)).catch(d=>{throw l({category:"fetch",message:`${m} ${i}`,data:{error:d.message,duration:Date.now()-u}}),d})};let s=XMLHttpRequest.prototype.open,a=XMLHttpRequest.prototype.send;if(XMLHttpRequest.prototype.open=function(r,t){return this._scoutMethod=r,this._scoutUrl=t,s.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){let r=this,t=Date.now();return r.addEventListener("loadend",()=>{l({category:"xhr",message:`${r._scoutMethod||"GET"} ${r._scoutUrl||""}`,data:{status:r.status,duration:Date.now()-t}})}),a.apply(this,arguments)},n.addErrorEventListener&&window.addEventListener("error",async r=>{if(n.enabled){try{let t=r.error?r.error.stack:"No stack trace available";if(h(r.message))return;n.sendErrors&&f({type:"window.onerror",message:r.message,source:r.filename,lineno:r.lineno,colno:r.colno,errorTrace:t})}catch(t){w("[Scout] Error handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.addUnhandledRejectionEventListener&&window.addEventListener("unhandledrejection",r=>{if(n.enabled){try{let t=r.reason,i=t?.stack||"No stack trace available";if(h(t?.message||""))return;n.sendErrors&&f({type:"Unhandled Promise Rejection",message:t?.message||"Unhandled Promise Rejection",reason:r.reason,errorTrace:i})}catch(t){w("[Scout] Rejection handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.overrideConsoleError&&(console.error=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.error",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.error override failure:",t)}}),n.overrideConsoleWarn&&(console.warn=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.warn",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.warn override failure:",t)}}),n.loadUAParser&&n.browserDetails){let r=document.createElement("script");r.src="https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js",r.async=!0,r.onload=()=>{typeof UAParser<"u"&&(window._uaParserResult=new UAParser().getResult())},document.head.appendChild(r)}}function q(e={},o={}){if(e.user&&(g=e.user,delete e.user),_){c={...c,...e},n={...n,...o};return}c={...c,...e},n={...n,...o},_=!0,typeof window<"u"&&(X(),window.Scout={init:(s,a)=>{s?.user&&(g=s.user,delete s.user),c={...c,...s},a&&(n={...n,...a})},setScope:s=>{c={...c,...s}},setConfig:s=>{n={...n,...s}},setUser:R,setContext:C,setTag:M,addBreadcrumb:l,error:T})}
4
+ `):[];for(let t=1;t<r.length;t++){let i=r[t].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}n.debug&&I("[Scout] Sending:",s),n.endpoint&&F(n.endpoint,s)}function T(e){n.enabled&&f(e)}function R(e){g=e}function C(e){p={...p,...e}}function M(e,o){p[e]=o}function W(e){l(e)}function X(){if(n.trackUserInteractions){document.addEventListener("click",t=>{y.clicks++;let i=t.target,m=i.tagName?i.tagName.toLowerCase():"",u=(i.textContent||"").trim().slice(0,50);l({category:"click",message:m+(u?": "+u:"")})});let r=0;window.addEventListener("scroll",()=>{let t=Date.now();t-r>100&&(y.scrolls++,r=t)})}let e=history.pushState;history.pushState=function(){e.apply(this,arguments),l({category:"navigation",message:window.location.href})},window.addEventListener("popstate",()=>{l({category:"navigation",message:window.location.href})});let o=window.fetch;window.fetch=function(r,t){let i=typeof r=="string"?r:r?.url||"",m=t?.method||"GET",u=Date.now();return o.apply(this,arguments).then(d=>(l({category:"fetch",message:`${m} ${i}`,data:{status:d.status,duration:Date.now()-u}}),d)).catch(d=>{throw l({category:"fetch",message:`${m} ${i}`,data:{error:d.message,duration:Date.now()-u}}),d})};let s=XMLHttpRequest.prototype.open,a=XMLHttpRequest.prototype.send;if(XMLHttpRequest.prototype.open=function(r,t){return this._scoutMethod=r,this._scoutUrl=t,s.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){let r=this,t=Date.now();return r.addEventListener("loadend",()=>{l({category:"xhr",message:`${r._scoutMethod||"GET"} ${r._scoutUrl||""}`,data:{status:r.status,duration:Date.now()-t}})}),a.apply(this,arguments)},n.addErrorEventListener&&window.addEventListener("error",async r=>{if(n.enabled){try{let t=r.error?r.error.stack:"No stack trace available";if(h(r.message))return;n.sendErrors&&f({type:"window.onerror",message:r.message,source:r.filename,lineno:r.lineno,colno:r.colno,errorTrace:t})}catch(t){w("[Scout] Error handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.addUnhandledRejectionEventListener&&window.addEventListener("unhandledrejection",r=>{if(n.enabled){try{let t=r.reason,i=t?.stack||"No stack trace available";if(h(t?.message||""))return;n.sendErrors&&f({type:"Unhandled Promise Rejection",message:t?.message||"Unhandled Promise Rejection",reason:r.reason,errorTrace:i})}catch(t){w("[Scout] Rejection handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.overrideConsoleError&&(console.error=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.error",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.error override failure:",t)}}),n.overrideConsoleWarn&&(console.warn=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.warn",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.warn override failure:",t)}}),n.loadUAParser&&n.browserDetails){let r=document.createElement("script");r.src="https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js",r.async=!0,r.onload=()=>{typeof UAParser<"u"&&(window._uaParserResult=new UAParser().getResult())},document.head.appendChild(r)}}function V(e={},o={}){if(e.user&&(g=e.user,delete e.user),b){c={...c,...e},n={...n,...o};return}c={...c,...e},n={...n,...o},b=!0,typeof window<"u"&&(X(),window.Scout={init:(s,a)=>{s?.user&&(g=s.user,delete s.user),c={...c,...s},a&&(n={...n,...a})},setScope:s=>{c={...c,...s}},setConfig:s=>{n={...n,...s}},setUser:R,setContext:C,setTag:M,addBreadcrumb:l,error:T})}
5
5
  //# sourceMappingURL=index.cjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
+ "mappings": "4ZAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,mBAAAE,EAAA,iBAAAC,EAAA,SAAAC,EAAA,eAAAC,EAAA,WAAAC,EAAA,YAAAC,IAAA,eAAAC,EAAAR,GAWA,IAAMS,EAAgB,CACpB,sBAAuB,GACvB,kBAAmB,GACnB,iBAAkB,GAClB,iBAAkB,GAClB,eAAgB,GAChB,cAAe,GACf,aAAc,GACd,aAAc,KACd,WAAY,GACZ,WAAY,EACZ,QAAS,GACT,MAAO,GACP,SAAU,GACV,MAAO,KAEP,gBAAiB,GACjB,6BAA8B,GAC9B,sBAAuB,GACvB,mCAAoC,GAEpC,mBAAoB,GACpB,oBAAqB,GACrB,oBAAqB,GACrB,qBAAsB,EACxB,EAEIC,EAAS,CAAE,GAAGD,CAAc,EAE5BE,EAAQ,CACV,YAAa,OAAO,OAAW,KAAe,OAAO,UAAU,WAAa,YAAc,cAAgB,aAC1G,IAAK,aACL,WAAY,QACZ,QAAS,KACT,QAAS,KACT,QAAS,KACT,IAAK,IACP,EAEMC,EAAmB,CAAE,OAAQ,EAAG,QAAS,CAAE,EAC7CC,EAAa,KACbC,EAAc,GACdC,EAAc,KACdC,EAAgB,CAAC,EACfC,EAAc,CAAC,EACfC,EAAkB,GAIxB,IAAMC,EAAe,QAAQ,KAE7B,IAAMC,EAAc,QAAQ,IAI5B,SAASC,EAAWC,EAAQ,CAC1B,MAAO,GAAGA,CAAM,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAG,CAAC,CAAC,EAC7D,CAEA,SAASC,GAAS,CAChB,IAAMC,EAAS,aAAa,QAAQ,eAAe,IAAM,aAAa,QAAQ,gBAAiBH,EAAW,MAAM,CAAC,EAAG,aAAa,QAAQ,eAAe,GAClJI,EAAY,eAAe,QAAQ,kBAAkB,IAAM,eAAe,QAAQ,mBAAoBJ,EAAW,SAAS,CAAC,EAAG,eAAe,QAAQ,kBAAkB,GAC7K,OAAAK,EAAaA,GAAcL,EAAW,UAAU,EACzC,CAAE,WAAAK,EAAY,OAAAF,EAAQ,UAAAC,CAAU,CACzC,CAEA,SAASE,GAAa,CACpB,GAAI,OAAO,iBAAiB,SAAS,KAAM,OAAO,OAAO,gBAAgB,QAAQ,KACjF,IAAMC,EAAK,UAAU,UAWrB,MAVY,CACV,CAAE,EAAG,iBAAkB,EAAG,eAAgB,EAC1C,CAAE,EAAG,SAAU,EAAG,QAAS,EAC3B,CAAE,EAAG,kBAAmB,EAAG,gBAAiB,EAC5C,CAAE,EAAG,UAAW,EAAG,SAAU,EAC7B,CAAE,EAAG,iBAAkB,EAAG,eAAgB,EAC1C,CAAE,EAAG,SAAU,EAAG,QAAS,EAC3B,CAAE,EAAG,eAAgB,EAAG,mBAAoB,EAC5C,CAAE,EAAG,OAAQ,EAAG,MAAO,CACzB,EACW,KAAKC,GAAKD,EAAG,MAAMC,EAAE,CAAC,CAAC,GAAG,GAAK,SAC5C,CAEA,SAASC,GAAQ,CACf,GAAI,OAAO,iBAAiB,IAAI,KAAM,OAAO,OAAO,gBAAgB,GAAG,KACvE,IAAMF,EAAK,UAAU,UAQrB,MAPY,CACV,CAAE,EAAG,MAAO,EAAG,SAAU,EACzB,CAAE,EAAG,MAAO,EAAG,QAAS,EACxB,CAAE,EAAG,YAAa,EAAG,OAAQ,EAC7B,CAAE,EAAG,UAAW,EAAG,SAAU,EAC7B,CAAE,EAAG,cAAe,EAAG,KAAM,CAC/B,EACW,KAAKG,GAAKH,EAAG,MAAMG,EAAE,CAAC,CAAC,GAAG,GAAK,SAC5C,CAEA,SAASC,GAAwB,CAC/B,IAAMC,EAAO,UAAU,YAAc,UAAU,eAAiB,UAAU,iBAC1E,MAAO,CACL,eAAgBA,EAAOA,EAAK,cAAgB,UAC5C,UAAW,UAAU,UACrB,MAAO,OAAO,WACd,OAAQ,OAAO,YACf,YAAa,OAAO,MACpB,aAAc,OAAO,OACrB,eAAgB,KAAK,IAAI,EACzB,WAAY,KAAK,eAAe,EAAE,gBAAgB,EAAE,SACpD,cAAe,UAAU,UAAY,UAAU,aAC/C,YAAa,KAAK,MAAM,YAAY,IAAI,EAAI,GAAI,EAChD,aAAc,UAAU,cAAgB,UACxC,eAAgB,IAAI,KAAK,EAAE,kBAAkB,EAC7C,eAAgB,UAAU,cAC1B,IAAK,OAAO,SAAS,KACrB,KAAM,OAAO,SAAS,KACtB,SAAU,SAAS,SACnB,QAASN,EAAW,EACpB,eAAgB,OAAO,iBAAiB,SAAS,SAAW,KAC5D,GAAIG,EAAM,EACV,UAAW,OAAO,iBAAiB,IAAI,SAAW,KAClD,WAAY,OAAO,iBAAiB,QAAQ,MAAQ,KACpD,YAAa,OAAO,iBAAiB,QAAQ,OAAS,KACtD,aAAc,OAAO,iBAAiB,QAAQ,QAAU,KACxD,SAAU,KAAK,IAAI,EAAG,YAAY,OAAO,aAAe,YAAY,OAAO,eAAe,EAC1F,WAAYI,EAAiB,OAC7B,YAAaA,EAAiB,OAChC,CACF,CAEA,SAASC,EAAkBC,EAAK,CAC9B,MAAI,CAACC,EAAO,cAAgB,CAAC,MAAM,QAAQA,EAAO,YAAY,EAAU,GACjEA,EAAO,aAAa,KAAKC,GAC1B,OAAOA,GAAY,SAAiBF,EAAI,SAASE,CAAO,EACxDA,aAAmB,OAAeA,EAAQ,KAAKF,CAAG,EAC/C,EACR,CACH,CAEA,SAASG,EAASC,EAAKC,EAAM,CAC3B,IAAMC,EAAa,IAAI,gBACjBC,EAAU,WAAW,IAAMD,EAAW,MAAM,EAAG,GAAI,EAEnDE,EAAU,CAAE,eAAgB,kBAAmB,EACrD,OAAIP,EAAO,QAAOO,EAAQ,gBAAgB,EAAIP,EAAO,OAE9C,MAAMG,EAAK,CAChB,OAAQ,OACR,QAAAI,EACA,KAAM,KAAK,UAAUH,CAAI,EACzB,OAAQC,EAAW,MACrB,CAAC,EACE,KAAKG,IAAO,aAAaF,CAAO,EAAUE,EAAG,EAC7C,MAAM,IAAM,CAAE,aAAaF,CAAO,CAAE,CAAC,CAC1C,CAEA,SAASG,EAAaC,EAAM,CAC1B,IAAMC,GAAOD,EAAK,CAAC,GAAK,IAAM,GACxBE,EAAO,CAAC,GAAGF,CAAI,EACrB,OAAOC,EAAI,QAAQ,UAAYE,GAAM,CACnC,IAAMC,EAAIF,EAAK,MAAM,EACrB,OAAIC,IAAM,KAAa,OAAOC,CAAC,EAC3BD,IAAM,KAAa,OAAOC,CAAC,EAC3BD,IAAM,KAAa,KAAK,UAAUC,CAAC,EAChCD,CACT,CAAC,CACH,CAIA,SAASE,EAAeC,EAAO,CAC7BC,EAAY,KAAK,CAAE,UAAW,KAAK,IAAI,EAAG,GAAGD,CAAM,CAAC,EAChDC,EAAY,OAASC,GAAiBD,EAAY,MAAM,CAC9D,CAIA,eAAeE,EAAeC,EAAK,CACjC,IAAMC,EAAUrB,EAAO,eAAiBL,EAAsB,EAAI,CAAC,EAC7D2B,EAAQ,OAAO,OAAOF,EAAKC,EAASE,EAAOrC,EAAO,CAAC,EAMzD,GAJIsC,IAAaF,EAAM,KAAOE,GAC1B,OAAO,KAAKC,CAAa,EAAE,SAAQH,EAAM,QAAU,CAAE,GAAGG,CAAc,GAC1EH,EAAM,YAAcL,EAAY,MAAM,EAElCjB,EAAO,YAAc,KAAK,OAAO,EAAK,EAAI,WAAWA,EAAO,UAAU,EAAI,CACxEA,EAAO,OAAOjB,EAAY,gCAAgC,EAC9D,MACF,CAKA,GAHKiB,EAAO,mBAAkBoB,EAAI,WAAa,MAG3CA,EAAI,WACN,GAAI,CACF,IAAMM,EAAQN,EAAI,WAAW,MAAM;AAAA,CAAI,EACjCO,EAAW,CAACD,EAAM,CAAC,CAAC,EAC1B,QAASE,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAC5B,CAACF,EAAME,CAAC,EAAE,SAAS,QAAQ,GAAK,CAACF,EAAME,CAAC,EAAE,SAAS,UAAU,GAAK,CAACF,EAAME,CAAC,EAAE,SAAS,aAAa,GACpGD,EAAS,KAAKD,EAAME,CAAC,CAAC,EAGtBD,EAAS,OAAS,IAAGP,EAAI,WAAaO,EAAS,KAAK;AAAA,CAAI,EAC9D,MAAY,CAAe,CAG7B,IAAKP,EAAI,YAAcA,EAAI,QAAU,CAACA,EAAI,OACxC,GAAI,CACF,IAAMS,EAAQT,EAAI,YAAcA,EAAI,MAC9BM,EAAQG,EAAQA,EAAM,MAAM;AAAA,CAAI,EAAI,CAAC,EAE3C,QAASD,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAAK,CACrC,IAAME,EAAQJ,EAAME,CAAC,EAAE,KAAK,EAAE,MAAM,uBAAuB,EAC3D,GAAIE,EAAO,CACTV,EAAI,OAASU,EAAM,CAAC,EACpBV,EAAI,OAAS,SAASU,EAAM,CAAC,EAAG,EAAE,EAClCV,EAAI,MAAQ,SAASU,EAAM,CAAC,EAAG,EAAE,EACjC,KACF,CACF,CACF,MAAY,CAAe,CAGzB9B,EAAO,OAAOjB,EAAY,mBAAoBuC,CAAK,EACnDtB,EAAO,UAAUE,EAASF,EAAO,SAAUsB,CAAK,CACtD,CAKO,SAASS,EAAaT,EAAO,CAC7BtB,EAAO,SACZmB,EAAeG,CAAK,CACtB,CAMO,SAASU,EAAQC,EAAM,CAC5BT,EAAcS,CAChB,CAMO,SAASC,EAAWC,EAAK,CAC9BV,EAAgB,CAAE,GAAGA,EAAe,GAAGU,CAAI,CAC7C,CAKO,SAASC,EAAOC,EAAKC,EAAO,CACjCb,EAAcY,CAAG,EAAIC,CACvB,CAMO,SAASC,EAAcvB,EAAO,CACnCD,EAAeC,CAAK,CACtB,CAIA,SAASwB,GAAiB,CAExB,GAAIxC,EAAO,sBAAuB,CAChC,SAAS,iBAAiB,QAAUyC,GAAM,CACxC5C,EAAiB,SACjB,IAAM6C,EAAKD,EAAE,OACPE,EAAMD,EAAG,QAAUA,EAAG,QAAQ,YAAY,EAAI,GAC9CE,GAAQF,EAAG,aAAe,IAAI,KAAK,EAAE,MAAM,EAAG,EAAE,EACtD3B,EAAe,CAAE,SAAU,QAAS,QAAS4B,GAAOC,EAAO,KAAOA,EAAO,GAAI,CAAC,CAChF,CAAC,EACD,IAAIC,EAAa,EACjB,OAAO,iBAAiB,SAAU,IAAM,CACtC,IAAMC,EAAM,KAAK,IAAI,EACjBA,EAAMD,EAAa,MAAOhD,EAAiB,UAAWgD,EAAaC,EACzE,CAAC,CACH,CAGA,IAAMC,EAAgB,QAAQ,UAC9B,QAAQ,UAAY,UAAW,CAC7BA,EAAc,MAAM,KAAM,SAAS,EACnChC,EAAe,CAAE,SAAU,aAAc,QAAS,OAAO,SAAS,IAAK,CAAC,CAC1E,EACA,OAAO,iBAAiB,WAAY,IAAM,CACxCA,EAAe,CAAE,SAAU,aAAc,QAAS,OAAO,SAAS,IAAK,CAAC,CAC1E,CAAC,EAGD,IAAMiC,EAAY,OAAO,MACzB,OAAO,MAAQ,SAASC,EAAOC,EAAM,CACnC,IAAM/C,EAAM,OAAO8C,GAAU,SAAWA,EAASA,GAAO,KAAO,GACzDE,EAASD,GAAM,QAAU,MACzBE,EAAQ,KAAK,IAAI,EACvB,OAAOJ,EAAU,MAAM,KAAM,SAAS,EAAE,KAAKK,IAC3CtC,EAAe,CAAE,SAAU,QAAS,QAAS,GAAGoC,CAAM,IAAIhD,CAAG,GAAI,KAAM,CAAE,OAAQkD,EAAS,OAAQ,SAAU,KAAK,IAAI,EAAID,CAAM,CAAE,CAAC,EAC3HC,EACR,EAAE,MAAMC,GAAO,CACd,MAAAvC,EAAe,CAAE,SAAU,QAAS,QAAS,GAAGoC,CAAM,IAAIhD,CAAG,GAAI,KAAM,CAAE,MAAOmD,EAAI,QAAS,SAAU,KAAK,IAAI,EAAIF,CAAM,CAAE,CAAC,EACvHE,CACR,CAAC,CACH,EAGA,IAAMC,EAAW,eAAe,UAAU,KACpCC,EAAW,eAAe,UAAU,KAsF1C,GArFA,eAAe,UAAU,KAAO,SAASL,EAAQhD,EAAK,CACpD,YAAK,aAAegD,EACpB,KAAK,UAAYhD,EACVoD,EAAS,MAAM,KAAM,SAAS,CACvC,EACA,eAAe,UAAU,KAAO,UAAW,CACzC,IAAME,EAAO,KACPL,EAAQ,KAAK,IAAI,EACvB,OAAAK,EAAK,iBAAiB,UAAW,IAAM,CACrC1C,EAAe,CAAE,SAAU,MAAO,QAAS,GAAG0C,EAAK,cAAgB,KAAK,IAAIA,EAAK,WAAa,EAAE,GAAI,KAAM,CAAE,OAAQA,EAAK,OAAQ,SAAU,KAAK,IAAI,EAAIL,CAAM,CAAE,CAAC,CACnK,CAAC,EACMI,EAAS,MAAM,KAAM,SAAS,CACvC,EAGIxD,EAAO,uBACT,OAAO,iBAAiB,QAAS,MAAOsB,GAAU,CAChD,GAAKtB,EAAO,QACZ,IAAI,CACF,IAAM0D,EAAapC,EAAM,MAAQA,EAAM,MAAM,MAAQ,2BACrD,GAAIxB,EAAkBwB,EAAM,OAAO,EAAG,OAClCtB,EAAO,YACTmB,EAAe,CACb,KAAM,iBACN,QAASG,EAAM,QACf,OAAQA,EAAM,SACd,OAAQA,EAAM,OACd,MAAOA,EAAM,MACb,WAAAoC,CACF,CAAC,CAEL,OAASjB,EAAG,CACVkB,EAAa,iCAAkClB,CAAC,CAClD,CACIzC,EAAO,mBAAmBsB,EAAM,eAAe,EACrD,CAAC,EAICtB,EAAO,oCACT,OAAO,iBAAiB,qBAAuBsB,GAAU,CACvD,GAAKtB,EAAO,QACZ,IAAI,CACF,IAAM4D,EAAQtC,EAAM,OACdoC,EAAaE,GAAO,OAAS,2BACnC,GAAI9D,EAAkB8D,GAAO,SAAW,EAAE,EAAG,OACzC5D,EAAO,YACTmB,EAAe,CACb,KAAM,8BACN,QAASyC,GAAO,SAAW,8BAC3B,OAAQtC,EAAM,OACd,WAAAoC,CACF,CAAC,CAEL,OAASjB,EAAG,CACVkB,EAAa,qCAAsClB,CAAC,CACtD,CACIzC,EAAO,mBAAmBsB,EAAM,eAAe,EACrD,CAAC,EAICtB,EAAO,uBACT,QAAQ,MAAQ,YAAaU,EAAM,CACjC,GAAKV,EAAO,QACZ,GAAI,CACF,IAAM0D,EAAa,IAAI,MAAM,EAAE,MAC/B,GAAI5D,EAAkBW,EAAaC,CAAI,CAAC,EAAG,OACvCV,EAAO,YAAYmB,EAAe,CAAE,KAAM,gBAAiB,WAAAuC,EAAY,KAAMjD,EAAaC,CAAI,CAAE,CAAC,CACvG,OAAS+B,EAAG,CAAEkB,EAAa,0CAA2ClB,CAAC,CAAE,CAC3E,GAGEzC,EAAO,sBACT,QAAQ,KAAO,YAAaU,EAAM,CAChC,GAAKV,EAAO,QACZ,GAAI,CACF,IAAM0D,EAAa,IAAI,MAAM,EAAE,MAC/B,GAAI5D,EAAkBW,EAAaC,CAAI,CAAC,EAAG,OACvCV,EAAO,YAAYmB,EAAe,CAAE,KAAM,eAAgB,WAAAuC,EAAY,KAAMjD,EAAaC,CAAI,CAAE,CAAC,CACtG,OAAS+B,EAAG,CAAEkB,EAAa,yCAA0ClB,CAAC,CAAE,CAC1E,GAIEzC,EAAO,cAAgBA,EAAO,eAAgB,CAChD,IAAM6D,EAAI,SAAS,cAAc,QAAQ,EACzCA,EAAE,IAAM,kEACRA,EAAE,MAAQ,GACVA,EAAE,OAAS,IAAM,CACX,OAAO,SAAa,MACtB,OAAO,gBAAkB,IAAI,SAAS,EAAE,UAAU,EAEtD,EACA,SAAS,KAAK,YAAYA,CAAC,CAC7B,CACF,CAQO,SAASX,EAAKY,EAAe,CAAC,EAAGC,EAAgB,CAAC,EAAG,CAO1D,GALID,EAAa,OACftC,EAAcsC,EAAa,KAC3B,OAAOA,EAAa,MAGlBE,EAAa,CACfzC,EAAQ,CAAE,GAAGA,EAAO,GAAGuC,CAAa,EACpC9D,EAAS,CAAE,GAAGA,EAAQ,GAAG+D,CAAc,EACvC,MACF,CAEAxC,EAAQ,CAAE,GAAGA,EAAO,GAAGuC,CAAa,EACpC9D,EAAS,CAAE,GAAGA,EAAQ,GAAG+D,CAAc,EACvCC,EAAc,GAEV,OAAO,OAAW,MACpBxB,EAAe,EAEf,OAAO,MAAQ,CACb,KAAM,CAAC,EAAGyB,IAAM,CAAM,GAAG,OAAQzC,EAAc,EAAE,KAAM,OAAO,EAAE,MAAQD,EAAQ,CAAE,GAAGA,EAAO,GAAG,CAAE,EAAO0C,IAAGjE,EAAS,CAAE,GAAGA,EAAQ,GAAGiE,CAAE,EAAE,EACxI,SAAW,GAAM,CAAE1C,EAAQ,CAAE,GAAGA,EAAO,GAAG,CAAE,CAAE,EAC9C,UAAY0C,GAAM,CAAEjE,EAAS,CAAE,GAAGA,EAAQ,GAAGiE,CAAE,CAAE,EACjD,QAAAjC,EACA,WAAAE,EACA,OAAAE,EACA,cAAerB,EACf,MAAOgB,CACT,EAEJ",
6
6
  "names": ["index_exports", "__export", "addBreadcrumb", "captureError", "init", "setContext", "setTag", "setUser", "__toCommonJS", "defaultConfig", "config", "scope", "userInteractions", "pageloadId", "initialized", "userContext", "customContext", "breadcrumbs", "MAX_BREADCRUMBS", "_consoleWarn", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "o", "captureBrowserDetails", "conn", "userInteractions", "shouldIgnoreError", "msg", "config", "pattern", "postData", "url", "data", "controller", "timeout", "headers", "r", "argsToString", "args", "fmt", "rest", "m", "v", "_addBreadcrumb", "crumb", "breadcrumbs", "MAX_BREADCRUMBS", "pushErrorEvent", "obj", "details", "event", "scope", "userContext", "customContext", "lines", "filtered", "i", "stack", "match", "captureError", "setUser", "user", "setContext", "ctx", "setTag", "key", "value", "addBreadcrumb", "setupListeners", "e", "el", "tag", "text", "lastScroll", "now", "origPushState", "origFetch", "input", "init", "method", "start", "response", "err", "origOpen", "origSend", "self", "errorTrace", "_consoleWarn", "error", "s", "scopeOptions", "configOptions", "initialized", "c"]
7
7
  }
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- var I={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},n={...I},c={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},E={clicks:0,scrolls:0},S=null,k=!1,g=null,p={},y=[],T=30;var w=console.warn;var _=console.log;function b(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function R(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",b("user")),localStorage.getItem("__scoutUserId")),a=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",b("session")),sessionStorage.getItem("__scoutSessionId"));return S=S||b("pageload"),{pageloadId:S,userId:e,sessionId:a}}function C(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(o=>e.match(o.p))?.n||"Unknown"}function M(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(o=>e.match(o.p))?.n||"Unknown"}function L(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:C(),browserVersion:window._uaParserResult?.browser?.version||null,os:M(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:E.clicks,userScrolls:E.scrolls}}function h(e){return!n.ignoreErrors||!Array.isArray(n.ignoreErrors)?!1:n.ignoreErrors.some(a=>typeof a=="string"?e.includes(a):a instanceof RegExp?a.test(e):!1)}function x(e,a){let o=new AbortController,s=setTimeout(()=>o.abort(),5e3),r={"Content-Type":"application/json"};return n.token&&(r["X-Ingest-Token"]=n.token),fetch(e,{method:"POST",headers:r,body:JSON.stringify(a),signal:o.signal}).then(t=>(clearTimeout(s),t)).catch(()=>{clearTimeout(s)})}function v(e){let a=(e[0]||"")+"",o=[...e];return a.replace(/%[sdj]/g,s=>{let r=o.shift();return s==="%s"?String(r):s==="%d"?Number(r):s==="%j"?JSON.stringify(r):s})}function l(e){y.push({timestamp:Date.now(),...e}),y.length>T&&y.shift()}async function f(e){let a=n.browserDetails?L():{},o=Object.assign(e,a,c,R());if(g&&(o.user=g),Object.keys(p).length&&(o.context={...p}),o.breadcrumbs=y.slice(),n.sampleRate&&Math.random()<1-parseFloat(n.sampleRate)){n.debug&&_("[Scout] Suppressed by sampling");return}if(n.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let s=e.errorTrace.split(`
1
+ var I={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},n={...I},c={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},y={clicks:0,scrolls:0},S=null,k=!1,g=null,p={},E=[],T=30;var w=console.warn;var b=console.log;function _(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function R(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",_("user")),localStorage.getItem("__scoutUserId")),a=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",_("session")),sessionStorage.getItem("__scoutSessionId"));return S=S||_("pageload"),{pageloadId:S,userId:e,sessionId:a}}function C(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(o=>e.match(o.p))?.n||"Unknown"}function M(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(o=>e.match(o.p))?.n||"Unknown"}function L(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:C(),browserVersion:window._uaParserResult?.browser?.version||null,os:M(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:y.clicks,userScrolls:y.scrolls}}function h(e){return!n.ignoreErrors||!Array.isArray(n.ignoreErrors)?!1:n.ignoreErrors.some(a=>typeof a=="string"?e.includes(a):a instanceof RegExp?a.test(e):!1)}function x(e,a){let o=new AbortController,s=setTimeout(()=>o.abort(),5e3),r={"Content-Type":"application/json"};return n.token&&(r["X-Ingest-Token"]=n.token),fetch(e,{method:"POST",headers:r,body:JSON.stringify(a),signal:o.signal}).then(t=>(clearTimeout(s),t)).catch(()=>{clearTimeout(s)})}function v(e){let a=(e[0]||"")+"",o=[...e];return a.replace(/%[sdj]/g,s=>{let r=o.shift();return s==="%s"?String(r):s==="%d"?Number(r):s==="%j"?JSON.stringify(r):s})}function l(e){E.push({timestamp:Date.now(),...e}),E.length>T&&E.shift()}async function f(e){let a=n.browserDetails?L():{},o=Object.assign(e,a,c,R());if(g&&(o.user=g),Object.keys(p).length&&(o.context={...p}),o.breadcrumbs=E.slice(),n.sampleRate&&Math.random()<1-parseFloat(n.sampleRate)){n.debug&&b("[Scout] Suppressed by sampling");return}if(n.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let s=e.errorTrace.split(`
2
2
  `),r=[s[0]];for(let t=1;t<s.length;t++)!s[t].includes("/scout")&&!s[t].includes("scout.js")&&!s[t].includes("scout-error")&&r.push(s[t]);r.length>1&&(e.errorTrace=r.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let s=e.errorTrace||e.stack,r=s?s.split(`
4
- `):[];for(let t=1;t<r.length;t++){let i=r[t].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}n.debug&&_("[Scout] Sending:",o),n.endpoint&&x(n.endpoint,o)}function P(e){n.enabled&&f(e)}function U(e){g=e}function D(e){p={...p,...e}}function A(e,a){p[e]=a}function H(e){l(e)}function O(){if(n.trackUserInteractions){document.addEventListener("click",t=>{E.clicks++;let i=t.target,m=i.tagName?i.tagName.toLowerCase():"",u=(i.textContent||"").trim().slice(0,50);l({category:"click",message:m+(u?": "+u:"")})});let r=0;window.addEventListener("scroll",()=>{let t=Date.now();t-r>100&&(E.scrolls++,r=t)})}let e=history.pushState;history.pushState=function(){e.apply(this,arguments),l({category:"navigation",message:window.location.href})},window.addEventListener("popstate",()=>{l({category:"navigation",message:window.location.href})});let a=window.fetch;window.fetch=function(r,t){let i=typeof r=="string"?r:r?.url||"",m=t?.method||"GET",u=Date.now();return a.apply(this,arguments).then(d=>(l({category:"fetch",message:`${m} ${i}`,data:{status:d.status,duration:Date.now()-u}}),d)).catch(d=>{throw l({category:"fetch",message:`${m} ${i}`,data:{error:d.message,duration:Date.now()-u}}),d})};let o=XMLHttpRequest.prototype.open,s=XMLHttpRequest.prototype.send;if(XMLHttpRequest.prototype.open=function(r,t){return this._scoutMethod=r,this._scoutUrl=t,o.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){let r=this,t=Date.now();return r.addEventListener("loadend",()=>{l({category:"xhr",message:`${r._scoutMethod||"GET"} ${r._scoutUrl||""}`,data:{status:r.status,duration:Date.now()-t}})}),s.apply(this,arguments)},n.addErrorEventListener&&window.addEventListener("error",async r=>{if(n.enabled){try{let t=r.error?r.error.stack:"No stack trace available";if(h(r.message))return;n.sendErrors&&f({type:"window.onerror",message:r.message,source:r.filename,lineno:r.lineno,colno:r.colno,errorTrace:t})}catch(t){w("[Scout] Error handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.addUnhandledRejectionEventListener&&window.addEventListener("unhandledrejection",r=>{if(n.enabled){try{let t=r.reason,i=t?.stack||"No stack trace available";if(h(t?.message||""))return;n.sendErrors&&f({type:"Unhandled Promise Rejection",message:t?.message||"Unhandled Promise Rejection",reason:r.reason,errorTrace:i})}catch(t){w("[Scout] Rejection handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.overrideConsoleError&&(console.error=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.error",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.error override failure:",t)}}),n.overrideConsoleWarn&&(console.warn=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.warn",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.warn override failure:",t)}}),n.loadUAParser&&n.browserDetails){let r=document.createElement("script");r.src="https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js",r.async=!0,r.onload=()=>{typeof UAParser<"u"&&(window._uaParserResult=new UAParser().getResult())},document.head.appendChild(r)}}function $(e={},a={}){if(e.user&&(g=e.user,delete e.user),k){c={...c,...e},n={...n,...a};return}c={...c,...e},n={...n,...a},k=!0,typeof window<"u"&&(O(),window.Scout={init:(o,s)=>{o?.user&&(g=o.user,delete o.user),c={...c,...o},s&&(n={...n,...s})},setScope:o=>{c={...c,...o}},setConfig:o=>{n={...n,...o}},setUser:U,setContext:D,setTag:A,addBreadcrumb:l,error:P})}export{H as addBreadcrumb,P as captureError,$ as init,D as setContext,A as setTag,U as setUser};
4
+ `):[];for(let t=1;t<r.length;t++){let i=r[t].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}n.debug&&b("[Scout] Sending:",o),n.endpoint&&x(n.endpoint,o)}function P(e){n.enabled&&f(e)}function U(e){g=e}function D(e){p={...p,...e}}function A(e,a){p[e]=a}function H(e){l(e)}function O(){if(n.trackUserInteractions){document.addEventListener("click",t=>{y.clicks++;let i=t.target,m=i.tagName?i.tagName.toLowerCase():"",u=(i.textContent||"").trim().slice(0,50);l({category:"click",message:m+(u?": "+u:"")})});let r=0;window.addEventListener("scroll",()=>{let t=Date.now();t-r>100&&(y.scrolls++,r=t)})}let e=history.pushState;history.pushState=function(){e.apply(this,arguments),l({category:"navigation",message:window.location.href})},window.addEventListener("popstate",()=>{l({category:"navigation",message:window.location.href})});let a=window.fetch;window.fetch=function(r,t){let i=typeof r=="string"?r:r?.url||"",m=t?.method||"GET",u=Date.now();return a.apply(this,arguments).then(d=>(l({category:"fetch",message:`${m} ${i}`,data:{status:d.status,duration:Date.now()-u}}),d)).catch(d=>{throw l({category:"fetch",message:`${m} ${i}`,data:{error:d.message,duration:Date.now()-u}}),d})};let o=XMLHttpRequest.prototype.open,s=XMLHttpRequest.prototype.send;if(XMLHttpRequest.prototype.open=function(r,t){return this._scoutMethod=r,this._scoutUrl=t,o.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){let r=this,t=Date.now();return r.addEventListener("loadend",()=>{l({category:"xhr",message:`${r._scoutMethod||"GET"} ${r._scoutUrl||""}`,data:{status:r.status,duration:Date.now()-t}})}),s.apply(this,arguments)},n.addErrorEventListener&&window.addEventListener("error",async r=>{if(n.enabled){try{let t=r.error?r.error.stack:"No stack trace available";if(h(r.message))return;n.sendErrors&&f({type:"window.onerror",message:r.message,source:r.filename,lineno:r.lineno,colno:r.colno,errorTrace:t})}catch(t){w("[Scout] Error handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.addUnhandledRejectionEventListener&&window.addEventListener("unhandledrejection",r=>{if(n.enabled){try{let t=r.reason,i=t?.stack||"No stack trace available";if(h(t?.message||""))return;n.sendErrors&&f({type:"Unhandled Promise Rejection",message:t?.message||"Unhandled Promise Rejection",reason:r.reason,errorTrace:i})}catch(t){w("[Scout] Rejection handler failure:",t)}n.selfHealingErrors&&r.preventDefault()}}),n.overrideConsoleError&&(console.error=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.error",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.error override failure:",t)}}),n.overrideConsoleWarn&&(console.warn=function(...r){if(n.enabled)try{let t=new Error().stack;if(h(v(r)))return;n.sendErrors&&f({type:"console.warn",errorTrace:t,args:v(r)})}catch(t){w("[Scout] console.warn override failure:",t)}}),n.loadUAParser&&n.browserDetails){let r=document.createElement("script");r.src="https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js",r.async=!0,r.onload=()=>{typeof UAParser<"u"&&(window._uaParserResult=new UAParser().getResult())},document.head.appendChild(r)}}function N(e={},a={}){if(e.user&&(g=e.user,delete e.user),k){c={...c,...e},n={...n,...a};return}c={...c,...e},n={...n,...a},k=!0,typeof window<"u"&&(O(),window.Scout={init:(o,s)=>{o?.user&&(g=o.user,delete o.user),c={...c,...o},s&&(n={...n,...s})},setScope:o=>{c={...c,...o}},setConfig:o=>{n={...n,...o}},setUser:U,setContext:D,setTag:A,addBreadcrumb:l,error:P})}export{H as addBreadcrumb,P as captureError,N as init,D as setContext,A as setTag,U as setUser};
5
5
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js"],
4
- "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
+ "mappings": "AAWA,IAAMA,EAAgB,CACpB,sBAAuB,GACvB,kBAAmB,GACnB,iBAAkB,GAClB,iBAAkB,GAClB,eAAgB,GAChB,cAAe,GACf,aAAc,GACd,aAAc,KACd,WAAY,GACZ,WAAY,EACZ,QAAS,GACT,MAAO,GACP,SAAU,GACV,MAAO,KAEP,gBAAiB,GACjB,6BAA8B,GAC9B,sBAAuB,GACvB,mCAAoC,GAEpC,mBAAoB,GACpB,oBAAqB,GACrB,oBAAqB,GACrB,qBAAsB,EACxB,EAEIC,EAAS,CAAE,GAAGD,CAAc,EAE5BE,EAAQ,CACV,YAAa,OAAO,OAAW,KAAe,OAAO,UAAU,WAAa,YAAc,cAAgB,aAC1G,IAAK,aACL,WAAY,QACZ,QAAS,KACT,QAAS,KACT,QAAS,KACT,IAAK,IACP,EAEMC,EAAmB,CAAE,OAAQ,EAAG,QAAS,CAAE,EAC7CC,EAAa,KACbC,EAAc,GACdC,EAAc,KACdC,EAAgB,CAAC,EACfC,EAAc,CAAC,EACfC,EAAkB,GAIxB,IAAMC,EAAe,QAAQ,KAE7B,IAAMC,EAAc,QAAQ,IAI5B,SAASC,EAAWC,EAAQ,CAC1B,MAAO,GAAGA,CAAM,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,OAAO,EAAG,CAAC,CAAC,EAC7D,CAEA,SAASC,GAAS,CAChB,IAAMC,EAAS,aAAa,QAAQ,eAAe,IAAM,aAAa,QAAQ,gBAAiBH,EAAW,MAAM,CAAC,EAAG,aAAa,QAAQ,eAAe,GAClJI,EAAY,eAAe,QAAQ,kBAAkB,IAAM,eAAe,QAAQ,mBAAoBJ,EAAW,SAAS,CAAC,EAAG,eAAe,QAAQ,kBAAkB,GAC7K,OAAAK,EAAaA,GAAcL,EAAW,UAAU,EACzC,CAAE,WAAAK,EAAY,OAAAF,EAAQ,UAAAC,CAAU,CACzC,CAEA,SAASE,GAAa,CACpB,GAAI,OAAO,iBAAiB,SAAS,KAAM,OAAO,OAAO,gBAAgB,QAAQ,KACjF,IAAMC,EAAK,UAAU,UAWrB,MAVY,CACV,CAAE,EAAG,iBAAkB,EAAG,eAAgB,EAC1C,CAAE,EAAG,SAAU,EAAG,QAAS,EAC3B,CAAE,EAAG,kBAAmB,EAAG,gBAAiB,EAC5C,CAAE,EAAG,UAAW,EAAG,SAAU,EAC7B,CAAE,EAAG,iBAAkB,EAAG,eAAgB,EAC1C,CAAE,EAAG,SAAU,EAAG,QAAS,EAC3B,CAAE,EAAG,eAAgB,EAAG,mBAAoB,EAC5C,CAAE,EAAG,OAAQ,EAAG,MAAO,CACzB,EACW,KAAKC,GAAKD,EAAG,MAAMC,EAAE,CAAC,CAAC,GAAG,GAAK,SAC5C,CAEA,SAASC,GAAQ,CACf,GAAI,OAAO,iBAAiB,IAAI,KAAM,OAAO,OAAO,gBAAgB,GAAG,KACvE,IAAMF,EAAK,UAAU,UAQrB,MAPY,CACV,CAAE,EAAG,MAAO,EAAG,SAAU,EACzB,CAAE,EAAG,MAAO,EAAG,QAAS,EACxB,CAAE,EAAG,YAAa,EAAG,OAAQ,EAC7B,CAAE,EAAG,UAAW,EAAG,SAAU,EAC7B,CAAE,EAAG,cAAe,EAAG,KAAM,CAC/B,EACW,KAAK,GAAKA,EAAG,MAAM,EAAE,CAAC,CAAC,GAAG,GAAK,SAC5C,CAEA,SAASG,GAAwB,CAC/B,IAAMC,EAAO,UAAU,YAAc,UAAU,eAAiB,UAAU,iBAC1E,MAAO,CACL,eAAgBA,EAAOA,EAAK,cAAgB,UAC5C,UAAW,UAAU,UACrB,MAAO,OAAO,WACd,OAAQ,OAAO,YACf,YAAa,OAAO,MACpB,aAAc,OAAO,OACrB,eAAgB,KAAK,IAAI,EACzB,WAAY,KAAK,eAAe,EAAE,gBAAgB,EAAE,SACpD,cAAe,UAAU,UAAY,UAAU,aAC/C,YAAa,KAAK,MAAM,YAAY,IAAI,EAAI,GAAI,EAChD,aAAc,UAAU,cAAgB,UACxC,eAAgB,IAAI,KAAK,EAAE,kBAAkB,EAC7C,eAAgB,UAAU,cAC1B,IAAK,OAAO,SAAS,KACrB,KAAM,OAAO,SAAS,KACtB,SAAU,SAAS,SACnB,QAASL,EAAW,EACpB,eAAgB,OAAO,iBAAiB,SAAS,SAAW,KAC5D,GAAIG,EAAM,EACV,UAAW,OAAO,iBAAiB,IAAI,SAAW,KAClD,WAAY,OAAO,iBAAiB,QAAQ,MAAQ,KACpD,YAAa,OAAO,iBAAiB,QAAQ,OAAS,KACtD,aAAc,OAAO,iBAAiB,QAAQ,QAAU,KACxD,SAAU,KAAK,IAAI,EAAG,YAAY,OAAO,aAAe,YAAY,OAAO,eAAe,EAC1F,WAAYG,EAAiB,OAC7B,YAAaA,EAAiB,OAChC,CACF,CAEA,SAASC,EAAkBC,EAAK,CAC9B,MAAI,CAACC,EAAO,cAAgB,CAAC,MAAM,QAAQA,EAAO,YAAY,EAAU,GACjEA,EAAO,aAAa,KAAKC,GAC1B,OAAOA,GAAY,SAAiBF,EAAI,SAASE,CAAO,EACxDA,aAAmB,OAAeA,EAAQ,KAAKF,CAAG,EAC/C,EACR,CACH,CAEA,SAASG,EAASC,EAAKC,EAAM,CAC3B,IAAMC,EAAa,IAAI,gBACjBC,EAAU,WAAW,IAAMD,EAAW,MAAM,EAAG,GAAI,EAEnDE,EAAU,CAAE,eAAgB,kBAAmB,EACrD,OAAIP,EAAO,QAAOO,EAAQ,gBAAgB,EAAIP,EAAO,OAE9C,MAAMG,EAAK,CAChB,OAAQ,OACR,QAAAI,EACA,KAAM,KAAK,UAAUH,CAAI,EACzB,OAAQC,EAAW,MACrB,CAAC,EACE,KAAKG,IAAO,aAAaF,CAAO,EAAUE,EAAG,EAC7C,MAAM,IAAM,CAAE,aAAaF,CAAO,CAAE,CAAC,CAC1C,CAEA,SAASG,EAAaC,EAAM,CAC1B,IAAMC,GAAOD,EAAK,CAAC,GAAK,IAAM,GACxBE,EAAO,CAAC,GAAGF,CAAI,EACrB,OAAOC,EAAI,QAAQ,UAAYE,GAAM,CACnC,IAAMC,EAAIF,EAAK,MAAM,EACrB,OAAIC,IAAM,KAAa,OAAOC,CAAC,EAC3BD,IAAM,KAAa,OAAOC,CAAC,EAC3BD,IAAM,KAAa,KAAK,UAAUC,CAAC,EAChCD,CACT,CAAC,CACH,CAIA,SAASE,EAAeC,EAAO,CAC7BC,EAAY,KAAK,CAAE,UAAW,KAAK,IAAI,EAAG,GAAGD,CAAM,CAAC,EAChDC,EAAY,OAASC,GAAiBD,EAAY,MAAM,CAC9D,CAIA,eAAeE,EAAeC,EAAK,CACjC,IAAMC,EAAUrB,EAAO,eAAiBL,EAAsB,EAAI,CAAC,EAC7D2B,EAAQ,OAAO,OAAOF,EAAKC,EAASE,EAAOpC,EAAO,CAAC,EAMzD,GAJIqC,IAAaF,EAAM,KAAOE,GAC1B,OAAO,KAAKC,CAAa,EAAE,SAAQH,EAAM,QAAU,CAAE,GAAGG,CAAc,GAC1EH,EAAM,YAAcL,EAAY,MAAM,EAElCjB,EAAO,YAAc,KAAK,OAAO,EAAK,EAAI,WAAWA,EAAO,UAAU,EAAI,CACxEA,EAAO,OAAOhB,EAAY,gCAAgC,EAC9D,MACF,CAKA,GAHKgB,EAAO,mBAAkBoB,EAAI,WAAa,MAG3CA,EAAI,WACN,GAAI,CACF,IAAMM,EAAQN,EAAI,WAAW,MAAM;AAAA,CAAI,EACjCO,EAAW,CAACD,EAAM,CAAC,CAAC,EAC1B,QAASE,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAC5B,CAACF,EAAME,CAAC,EAAE,SAAS,QAAQ,GAAK,CAACF,EAAME,CAAC,EAAE,SAAS,UAAU,GAAK,CAACF,EAAME,CAAC,EAAE,SAAS,aAAa,GACpGD,EAAS,KAAKD,EAAME,CAAC,CAAC,EAGtBD,EAAS,OAAS,IAAGP,EAAI,WAAaO,EAAS,KAAK;AAAA,CAAI,EAC9D,MAAY,CAAe,CAG7B,IAAKP,EAAI,YAAcA,EAAI,QAAU,CAACA,EAAI,OACxC,GAAI,CACF,IAAMS,EAAQT,EAAI,YAAcA,EAAI,MAC9BM,EAAQG,EAAQA,EAAM,MAAM;AAAA,CAAI,EAAI,CAAC,EAE3C,QAASD,EAAI,EAAGA,EAAIF,EAAM,OAAQE,IAAK,CACrC,IAAME,EAAQJ,EAAME,CAAC,EAAE,KAAK,EAAE,MAAM,uBAAuB,EAC3D,GAAIE,EAAO,CACTV,EAAI,OAASU,EAAM,CAAC,EACpBV,EAAI,OAAS,SAASU,EAAM,CAAC,EAAG,EAAE,EAClCV,EAAI,MAAQ,SAASU,EAAM,CAAC,EAAG,EAAE,EACjC,KACF,CACF,CACF,MAAY,CAAe,CAGzB9B,EAAO,OAAOhB,EAAY,mBAAoBsC,CAAK,EACnDtB,EAAO,UAAUE,EAASF,EAAO,SAAUsB,CAAK,CACtD,CAKO,SAASS,EAAaT,EAAO,CAC7BtB,EAAO,SACZmB,EAAeG,CAAK,CACtB,CAMO,SAASU,EAAQC,EAAM,CAC5BT,EAAcS,CAChB,CAMO,SAASC,EAAWC,EAAK,CAC9BV,EAAgB,CAAE,GAAGA,EAAe,GAAGU,CAAI,CAC7C,CAKO,SAASC,EAAOC,EAAKC,EAAO,CACjCb,EAAcY,CAAG,EAAIC,CACvB,CAMO,SAASC,EAAcvB,EAAO,CACnCD,EAAeC,CAAK,CACtB,CAIA,SAASwB,GAAiB,CAExB,GAAIxC,EAAO,sBAAuB,CAChC,SAAS,iBAAiB,QAAUyC,GAAM,CACxC5C,EAAiB,SACjB,IAAM6C,EAAKD,EAAE,OACPE,EAAMD,EAAG,QAAUA,EAAG,QAAQ,YAAY,EAAI,GAC9CE,GAAQF,EAAG,aAAe,IAAI,KAAK,EAAE,MAAM,EAAG,EAAE,EACtD3B,EAAe,CAAE,SAAU,QAAS,QAAS4B,GAAOC,EAAO,KAAOA,EAAO,GAAI,CAAC,CAChF,CAAC,EACD,IAAIC,EAAa,EACjB,OAAO,iBAAiB,SAAU,IAAM,CACtC,IAAMC,EAAM,KAAK,IAAI,EACjBA,EAAMD,EAAa,MAAOhD,EAAiB,UAAWgD,EAAaC,EACzE,CAAC,CACH,CAGA,IAAMC,EAAgB,QAAQ,UAC9B,QAAQ,UAAY,UAAW,CAC7BA,EAAc,MAAM,KAAM,SAAS,EACnChC,EAAe,CAAE,SAAU,aAAc,QAAS,OAAO,SAAS,IAAK,CAAC,CAC1E,EACA,OAAO,iBAAiB,WAAY,IAAM,CACxCA,EAAe,CAAE,SAAU,aAAc,QAAS,OAAO,SAAS,IAAK,CAAC,CAC1E,CAAC,EAGD,IAAMiC,EAAY,OAAO,MACzB,OAAO,MAAQ,SAASC,EAAOC,EAAM,CACnC,IAAM/C,EAAM,OAAO8C,GAAU,SAAWA,EAASA,GAAO,KAAO,GACzDE,EAASD,GAAM,QAAU,MACzBE,EAAQ,KAAK,IAAI,EACvB,OAAOJ,EAAU,MAAM,KAAM,SAAS,EAAE,KAAKK,IAC3CtC,EAAe,CAAE,SAAU,QAAS,QAAS,GAAGoC,CAAM,IAAIhD,CAAG,GAAI,KAAM,CAAE,OAAQkD,EAAS,OAAQ,SAAU,KAAK,IAAI,EAAID,CAAM,CAAE,CAAC,EAC3HC,EACR,EAAE,MAAMC,GAAO,CACd,MAAAvC,EAAe,CAAE,SAAU,QAAS,QAAS,GAAGoC,CAAM,IAAIhD,CAAG,GAAI,KAAM,CAAE,MAAOmD,EAAI,QAAS,SAAU,KAAK,IAAI,EAAIF,CAAM,CAAE,CAAC,EACvHE,CACR,CAAC,CACH,EAGA,IAAMC,EAAW,eAAe,UAAU,KACpCC,EAAW,eAAe,UAAU,KAsF1C,GArFA,eAAe,UAAU,KAAO,SAASL,EAAQhD,EAAK,CACpD,YAAK,aAAegD,EACpB,KAAK,UAAYhD,EACVoD,EAAS,MAAM,KAAM,SAAS,CACvC,EACA,eAAe,UAAU,KAAO,UAAW,CACzC,IAAME,EAAO,KACPL,EAAQ,KAAK,IAAI,EACvB,OAAAK,EAAK,iBAAiB,UAAW,IAAM,CACrC1C,EAAe,CAAE,SAAU,MAAO,QAAS,GAAG0C,EAAK,cAAgB,KAAK,IAAIA,EAAK,WAAa,EAAE,GAAI,KAAM,CAAE,OAAQA,EAAK,OAAQ,SAAU,KAAK,IAAI,EAAIL,CAAM,CAAE,CAAC,CACnK,CAAC,EACMI,EAAS,MAAM,KAAM,SAAS,CACvC,EAGIxD,EAAO,uBACT,OAAO,iBAAiB,QAAS,MAAOsB,GAAU,CAChD,GAAKtB,EAAO,QACZ,IAAI,CACF,IAAM0D,EAAapC,EAAM,MAAQA,EAAM,MAAM,MAAQ,2BACrD,GAAIxB,EAAkBwB,EAAM,OAAO,EAAG,OAClCtB,EAAO,YACTmB,EAAe,CACb,KAAM,iBACN,QAASG,EAAM,QACf,OAAQA,EAAM,SACd,OAAQA,EAAM,OACd,MAAOA,EAAM,MACb,WAAAoC,CACF,CAAC,CAEL,OAASjB,EAAG,CACVkB,EAAa,iCAAkClB,CAAC,CAClD,CACIzC,EAAO,mBAAmBsB,EAAM,eAAe,EACrD,CAAC,EAICtB,EAAO,oCACT,OAAO,iBAAiB,qBAAuBsB,GAAU,CACvD,GAAKtB,EAAO,QACZ,IAAI,CACF,IAAM4D,EAAQtC,EAAM,OACdoC,EAAaE,GAAO,OAAS,2BACnC,GAAI9D,EAAkB8D,GAAO,SAAW,EAAE,EAAG,OACzC5D,EAAO,YACTmB,EAAe,CACb,KAAM,8BACN,QAASyC,GAAO,SAAW,8BAC3B,OAAQtC,EAAM,OACd,WAAAoC,CACF,CAAC,CAEL,OAASjB,EAAG,CACVkB,EAAa,qCAAsClB,CAAC,CACtD,CACIzC,EAAO,mBAAmBsB,EAAM,eAAe,EACrD,CAAC,EAICtB,EAAO,uBACT,QAAQ,MAAQ,YAAaU,EAAM,CACjC,GAAKV,EAAO,QACZ,GAAI,CACF,IAAM0D,EAAa,IAAI,MAAM,EAAE,MAC/B,GAAI5D,EAAkBW,EAAaC,CAAI,CAAC,EAAG,OACvCV,EAAO,YAAYmB,EAAe,CAAE,KAAM,gBAAiB,WAAAuC,EAAY,KAAMjD,EAAaC,CAAI,CAAE,CAAC,CACvG,OAAS+B,EAAG,CAAEkB,EAAa,0CAA2ClB,CAAC,CAAE,CAC3E,GAGEzC,EAAO,sBACT,QAAQ,KAAO,YAAaU,EAAM,CAChC,GAAKV,EAAO,QACZ,GAAI,CACF,IAAM0D,EAAa,IAAI,MAAM,EAAE,MAC/B,GAAI5D,EAAkBW,EAAaC,CAAI,CAAC,EAAG,OACvCV,EAAO,YAAYmB,EAAe,CAAE,KAAM,eAAgB,WAAAuC,EAAY,KAAMjD,EAAaC,CAAI,CAAE,CAAC,CACtG,OAAS+B,EAAG,CAAEkB,EAAa,yCAA0ClB,CAAC,CAAE,CAC1E,GAIEzC,EAAO,cAAgBA,EAAO,eAAgB,CAChD,IAAM6D,EAAI,SAAS,cAAc,QAAQ,EACzCA,EAAE,IAAM,kEACRA,EAAE,MAAQ,GACVA,EAAE,OAAS,IAAM,CACX,OAAO,SAAa,MACtB,OAAO,gBAAkB,IAAI,SAAS,EAAE,UAAU,EAEtD,EACA,SAAS,KAAK,YAAYA,CAAC,CAC7B,CACF,CAQO,SAASX,EAAKY,EAAe,CAAC,EAAGC,EAAgB,CAAC,EAAG,CAO1D,GALID,EAAa,OACftC,EAAcsC,EAAa,KAC3B,OAAOA,EAAa,MAGlBE,EAAa,CACfzC,EAAQ,CAAE,GAAGA,EAAO,GAAGuC,CAAa,EACpC9D,EAAS,CAAE,GAAGA,EAAQ,GAAG+D,CAAc,EACvC,MACF,CAEAxC,EAAQ,CAAE,GAAGA,EAAO,GAAGuC,CAAa,EACpC9D,EAAS,CAAE,GAAGA,EAAQ,GAAG+D,CAAc,EACvCC,EAAc,GAEV,OAAO,OAAW,MACpBxB,EAAe,EAEf,OAAO,MAAQ,CACb,KAAM,CAACqB,EAAGI,IAAM,CAAMJ,GAAG,OAAQrC,EAAcqC,EAAE,KAAM,OAAOA,EAAE,MAAQtC,EAAQ,CAAE,GAAGA,EAAO,GAAGsC,CAAE,EAAOI,IAAGjE,EAAS,CAAE,GAAGA,EAAQ,GAAGiE,CAAE,EAAE,EACxI,SAAWJ,GAAM,CAAEtC,EAAQ,CAAE,GAAGA,EAAO,GAAGsC,CAAE,CAAE,EAC9C,UAAYI,GAAM,CAAEjE,EAAS,CAAE,GAAGA,EAAQ,GAAGiE,CAAE,CAAE,EACjD,QAAAjC,EACA,WAAAE,EACA,OAAAE,EACA,cAAerB,EACf,MAAOgB,CACT,EAEJ",
6
6
  "names": ["defaultConfig", "config", "scope", "userInteractions", "pageloadId", "initialized", "userContext", "customContext", "breadcrumbs", "MAX_BREADCRUMBS", "_consoleWarn", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "captureBrowserDetails", "conn", "userInteractions", "shouldIgnoreError", "msg", "config", "pattern", "postData", "url", "data", "controller", "timeout", "headers", "r", "argsToString", "args", "fmt", "rest", "m", "v", "_addBreadcrumb", "crumb", "breadcrumbs", "MAX_BREADCRUMBS", "pushErrorEvent", "obj", "details", "event", "scope", "userContext", "customContext", "lines", "filtered", "i", "stack", "match", "captureError", "setUser", "user", "setContext", "ctx", "setTag", "key", "value", "addBreadcrumb", "setupListeners", "e", "el", "tag", "text", "lastScroll", "now", "origPushState", "origFetch", "input", "init", "method", "start", "response", "err", "origOpen", "origSend", "self", "errorTrace", "_consoleWarn", "error", "s", "scopeOptions", "configOptions", "initialized", "c"]
7
7
  }
package/dist/node.cjs CHANGED
@@ -1,2 +1,2 @@
1
- var p=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var f=(e,t)=>{for(var s in t)p(e,s,{get:t[s],enumerable:!0})},k=(e,t,s,u)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of m(t))!g.call(e,r)&&r!==s&&p(e,r,{get:()=>t[r],enumerable:!(u=l(t,r))||u.enumerable});return e};var h=e=>k(p({},"__esModule",{value:!0}),e);var j={};f(j,{addBreadcrumb:()=>b,captureError:()=>O,errorHandlingMiddleware:()=>T,initTracker:()=>x,setContext:()=>D,setTag:()=>E,setUser:()=>y});module.exports=h(j);var n={debug:!1,endpoint:"",token:null,sendErrors:!0,captureUserDetails:!1,captureRequestDetails:!0,captureStackTrace:!0},a={environment:process.env.NODE_ENV||"production",project:null,release:null,version:null,sdk:"node",nodeVersion:process.version,platform:process.platform,arch:process.arch},d=null,o={},c=[],S=30;function i(e){if(n.debug&&console.error("[Scout]:",e),d&&(e.user=d),Object.keys(o).length&&(e.context={...o}),e.breadcrumbs=c.slice(),n.endpoint&&n.sendErrors){let t={"Content-Type":"application/json"};n.token&&(t["X-Ingest-Token"]=n.token),fetch(n.endpoint,{method:"POST",headers:t,body:JSON.stringify(e)}).catch(s=>{console.error("[Scout] Failed to send error:",s.message)})}}function x(e={},t={}){a={...a,...e},n={...n,...t},process.on("uncaughtException",s=>{i({type:"uncaughtException",message:s.message,stack:s.stack,errorTrace:s.stack,timestamp:new Date().toISOString(),...a})}),process.on("unhandledRejection",s=>{i({type:"unhandledRejection",message:s?.message||"Unhandled Promise Rejection",stack:s?.stack||"No stack trace",errorTrace:s?.stack||"No stack trace",timestamp:new Date().toISOString(),...a})})}function T(e,t,s,u){let r={type:"expressError",message:e.message,stack:n.captureStackTrace?e.stack:void 0,errorTrace:n.captureStackTrace?e.stack:void 0,path:t.originalUrl,method:t.method,params:t.params,query:t.query,headers:n.captureRequestDetails?t.headers:void 0,timestamp:new Date().toISOString(),...a};n.captureUserDetails&&t.user&&(r.user={id:t.user.id||t.user._id,email:t.user.email,name:t.user.name||t.user.username}),i(r),s.status(500).json({error:"Internal Server Error"})}function y(e){d=e}function D(e){o={...o,...e}}function E(e,t){o[e]=t}function b(e){c.push({timestamp:Date.now(),...e}),c.length>S&&c.shift()}function O(e,t={}){let s={type:"manual",message:e?.message||String(e),stack:e?.stack,errorTrace:e?.stack,timestamp:new Date().toISOString(),...a};Object.keys(t).length&&(s.context={...o,...t}),i(s)}0&&(module.exports={addBreadcrumb,captureError,errorHandlingMiddleware,initTracker,setContext,setTag,setUser});
1
+ var p=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var m=Object.getOwnPropertyNames;var g=Object.prototype.hasOwnProperty;var f=(e,t)=>{for(var s in t)p(e,s,{get:t[s],enumerable:!0})},k=(e,t,s,u)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of m(t))!g.call(e,r)&&r!==s&&p(e,r,{get:()=>t[r],enumerable:!(u=l(t,r))||u.enumerable});return e};var h=e=>k(p({},"__esModule",{value:!0}),e);var j={};f(j,{addBreadcrumb:()=>b,captureError:()=>O,errorHandlingMiddleware:()=>D,initTracker:()=>x,setContext:()=>T,setTag:()=>y,setUser:()=>E});module.exports=h(j);var n={debug:!1,endpoint:"",token:null,sendErrors:!0,captureUserDetails:!1,captureRequestDetails:!0,captureStackTrace:!0},a={environment:process.env.NODE_ENV||"production",project:null,release:null,version:null,sdk:"node",sdkVersion:"0.2.3",nodeVersion:process.version,platform:process.platform,arch:process.arch},d=null,o={},c=[],S=30;function i(e){if(n.debug&&console.error("[Scout]:",e),d&&(e.user=d),Object.keys(o).length&&(e.context={...o}),e.breadcrumbs=c.slice(),n.endpoint&&n.sendErrors){let t={"Content-Type":"application/json"};n.token&&(t["X-Ingest-Token"]=n.token),fetch(n.endpoint,{method:"POST",headers:t,body:JSON.stringify(e)}).catch(s=>{console.error("[Scout] Failed to send error:",s.message)})}}function x(e={},t={}){a={...a,...e},n={...n,...t},process.on("uncaughtException",s=>{i({type:"uncaughtException",message:s.message,stack:s.stack,errorTrace:s.stack,timestamp:new Date().toISOString(),...a})}),process.on("unhandledRejection",s=>{i({type:"unhandledRejection",message:s?.message||"Unhandled Promise Rejection",stack:s?.stack||"No stack trace",errorTrace:s?.stack||"No stack trace",timestamp:new Date().toISOString(),...a})})}function D(e,t,s,u){let r={type:"expressError",message:e.message,stack:n.captureStackTrace?e.stack:void 0,errorTrace:n.captureStackTrace?e.stack:void 0,path:t.originalUrl,method:t.method,params:t.params,query:t.query,headers:n.captureRequestDetails?t.headers:void 0,timestamp:new Date().toISOString(),...a};n.captureUserDetails&&t.user&&(r.user={id:t.user.id||t.user._id,email:t.user.email,name:t.user.name||t.user.username}),i(r),s.status(500).json({error:"Internal Server Error"})}function E(e){d=e}function T(e){o={...o,...e}}function y(e,t){o[e]=t}function b(e){c.push({timestamp:Date.now(),...e}),c.length>S&&c.shift()}function O(e,t={}){let s={type:"manual",message:e?.message||String(e),stack:e?.stack,errorTrace:e?.stack,timestamp:new Date().toISOString(),...a};Object.keys(t).length&&(s.context={...o,...t}),i(s)}0&&(module.exports={addBreadcrumb,captureError,errorHandlingMiddleware,initTracker,setContext,setTag,setUser});
2
2
  //# sourceMappingURL=node.cjs.map
package/dist/node.cjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/node.js"],
4
- "sourcesContent": ["/**\n * Scout.js Node.js SDK\n *\n * Captures uncaught exceptions, unhandled rejections, and Express errors.\n *\n * Usage:\n * import { initTracker, errorHandlingMiddleware } from 'scout-error/node'\n */\n\nlet config = {\n debug: false,\n endpoint: '',\n token: null,\n sendErrors: true,\n captureUserDetails: false,\n captureRequestDetails: true,\n captureStackTrace: true,\n}\n\nlet scope = {\n environment: process.env.NODE_ENV || 'production',\n project: null,\n release: null,\n version: null,\n sdk: 'node',\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n}\n\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\nfunction logError(details) {\n if (config.debug) {\n console.error('[Scout]:', details)\n }\n\n // Attach user, context, breadcrumbs\n if (userContext) details.user = userContext\n if (Object.keys(customContext).length) details.context = { ...customContext }\n details.breadcrumbs = breadcrumbs.slice()\n\n if (config.endpoint && config.sendErrors) {\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n fetch(config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(details),\n }).catch(err => {\n console.error('[Scout] Failed to send error:', err.message)\n })\n }\n}\n\n/**\n * Initialize the Node.js error tracker.\n */\nexport function initTracker(customScope = {}, customConfig = {}) {\n scope = { ...scope, ...customScope }\n config = { ...config, ...customConfig }\n\n process.on('uncaughtException', (error) => {\n logError({\n type: 'uncaughtException',\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n\n process.on('unhandledRejection', (reason) => {\n logError({\n type: 'unhandledRejection',\n message: reason?.message || 'Unhandled Promise Rejection',\n stack: reason?.stack || 'No stack trace',\n errorTrace: reason?.stack || 'No stack trace',\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n}\n\n/**\n * Express error handling middleware.\n */\nexport function errorHandlingMiddleware(err, req, res, next) {\n const details = {\n type: 'expressError',\n message: err.message,\n stack: config.captureStackTrace ? err.stack : undefined,\n errorTrace: config.captureStackTrace ? err.stack : undefined,\n path: req.originalUrl,\n method: req.method,\n params: req.params,\n query: req.query,\n headers: config.captureRequestDetails ? req.headers : undefined,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n\n // Auto-capture user from req.user if configured\n if (config.captureUserDetails && req.user) {\n details.user = {\n id: req.user.id || req.user._id,\n email: req.user.email,\n name: req.user.name || req.user.username,\n }\n }\n\n logError(details)\n res.status(500).json({ error: 'Internal Server Error' })\n}\n\n/**\n * Set identified user info.\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context.\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n */\nexport function addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n/**\n * Manually capture an error.\n */\nexport function captureError(error, extra = {}) {\n const details = {\n type: 'manual',\n message: error?.message || String(error),\n stack: error?.stack,\n errorTrace: error?.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n // Put extra fields into context so they show up in the UI\n if (Object.keys(extra).length) {\n details.context = { ...customContext, ...extra }\n }\n logError(details)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Node.js SDK\n *\n * Captures uncaught exceptions, unhandled rejections, and Express errors.\n *\n * Usage:\n * import { initTracker, errorHandlingMiddleware } from 'scout-error/node'\n */\n\nlet config = {\n debug: false,\n endpoint: '',\n token: null,\n sendErrors: true,\n captureUserDetails: false,\n captureRequestDetails: true,\n captureStackTrace: true,\n}\n\nlet scope = {\n environment: process.env.NODE_ENV || 'production',\n project: null,\n release: null,\n version: null,\n sdk: 'node',\n sdkVersion: __SDK_VERSION__,\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n}\n\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\nfunction logError(details) {\n if (config.debug) {\n console.error('[Scout]:', details)\n }\n\n // Attach user, context, breadcrumbs\n if (userContext) details.user = userContext\n if (Object.keys(customContext).length) details.context = { ...customContext }\n details.breadcrumbs = breadcrumbs.slice()\n\n if (config.endpoint && config.sendErrors) {\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n fetch(config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(details),\n }).catch(err => {\n console.error('[Scout] Failed to send error:', err.message)\n })\n }\n}\n\n/**\n * Initialize the Node.js error tracker.\n */\nexport function initTracker(customScope = {}, customConfig = {}) {\n scope = { ...scope, ...customScope }\n config = { ...config, ...customConfig }\n\n process.on('uncaughtException', (error) => {\n logError({\n type: 'uncaughtException',\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n\n process.on('unhandledRejection', (reason) => {\n logError({\n type: 'unhandledRejection',\n message: reason?.message || 'Unhandled Promise Rejection',\n stack: reason?.stack || 'No stack trace',\n errorTrace: reason?.stack || 'No stack trace',\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n}\n\n/**\n * Express error handling middleware.\n */\nexport function errorHandlingMiddleware(err, req, res, next) {\n const details = {\n type: 'expressError',\n message: err.message,\n stack: config.captureStackTrace ? err.stack : undefined,\n errorTrace: config.captureStackTrace ? err.stack : undefined,\n path: req.originalUrl,\n method: req.method,\n params: req.params,\n query: req.query,\n headers: config.captureRequestDetails ? req.headers : undefined,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n\n // Auto-capture user from req.user if configured\n if (config.captureUserDetails && req.user) {\n details.user = {\n id: req.user.id || req.user._id,\n email: req.user.email,\n name: req.user.name || req.user.username,\n }\n }\n\n logError(details)\n res.status(500).json({ error: 'Internal Server Error' })\n}\n\n/**\n * Set identified user info.\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context.\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n */\nexport function addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n/**\n * Manually capture an error.\n */\nexport function captureError(error, extra = {}) {\n const details = {\n type: 'manual',\n message: error?.message || String(error),\n stack: error?.stack,\n errorTrace: error?.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n // Put extra fields into context so they show up in the UI\n if (Object.keys(extra).length) {\n details.context = { ...customContext, ...extra }\n }\n logError(details)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["node_exports", "__export", "addBreadcrumb", "captureError", "errorHandlingMiddleware", "initTracker", "setContext", "setTag", "setUser", "__toCommonJS", "config", "scope", "userContext", "customContext", "breadcrumbs", "MAX_BREADCRUMBS", "logError", "details", "headers", "err", "customScope", "customConfig", "error", "reason", "req", "res", "next", "user", "ctx", "key", "value", "crumb", "extra"]
7
7
  }
package/dist/node.js CHANGED
@@ -1,2 +1,2 @@
1
- var n={debug:!1,endpoint:"",token:null,sendErrors:!0,captureUserDetails:!1,captureRequestDetails:!0,captureStackTrace:!0},r={environment:process.env.NODE_ENV||"production",project:null,release:null,version:null,sdk:"node",nodeVersion:process.version,platform:process.platform,arch:process.arch},i=null,a={},o=[],p=30;function c(e){if(n.debug&&console.error("[Scout]:",e),i&&(e.user=i),Object.keys(a).length&&(e.context={...a}),e.breadcrumbs=o.slice(),n.endpoint&&n.sendErrors){let t={"Content-Type":"application/json"};n.token&&(t["X-Ingest-Token"]=n.token),fetch(n.endpoint,{method:"POST",headers:t,body:JSON.stringify(e)}).catch(s=>{console.error("[Scout] Failed to send error:",s.message)})}}function l(e={},t={}){r={...r,...e},n={...n,...t},process.on("uncaughtException",s=>{c({type:"uncaughtException",message:s.message,stack:s.stack,errorTrace:s.stack,timestamp:new Date().toISOString(),...r})}),process.on("unhandledRejection",s=>{c({type:"unhandledRejection",message:s?.message||"Unhandled Promise Rejection",stack:s?.stack||"No stack trace",errorTrace:s?.stack||"No stack trace",timestamp:new Date().toISOString(),...r})})}function m(e,t,s,d){let u={type:"expressError",message:e.message,stack:n.captureStackTrace?e.stack:void 0,errorTrace:n.captureStackTrace?e.stack:void 0,path:t.originalUrl,method:t.method,params:t.params,query:t.query,headers:n.captureRequestDetails?t.headers:void 0,timestamp:new Date().toISOString(),...r};n.captureUserDetails&&t.user&&(u.user={id:t.user.id||t.user._id,email:t.user.email,name:t.user.name||t.user.username}),c(u),s.status(500).json({error:"Internal Server Error"})}function g(e){i=e}function f(e){a={...a,...e}}function k(e,t){a[e]=t}function h(e){o.push({timestamp:Date.now(),...e}),o.length>p&&o.shift()}function S(e,t={}){let s={type:"manual",message:e?.message||String(e),stack:e?.stack,errorTrace:e?.stack,timestamp:new Date().toISOString(),...r};Object.keys(t).length&&(s.context={...a,...t}),c(s)}export{h as addBreadcrumb,S as captureError,m as errorHandlingMiddleware,l as initTracker,f as setContext,k as setTag,g as setUser};
1
+ var n={debug:!1,endpoint:"",token:null,sendErrors:!0,captureUserDetails:!1,captureRequestDetails:!0,captureStackTrace:!0},r={environment:process.env.NODE_ENV||"production",project:null,release:null,version:null,sdk:"node",sdkVersion:"0.2.3",nodeVersion:process.version,platform:process.platform,arch:process.arch},i=null,a={},o=[],p=30;function c(e){if(n.debug&&console.error("[Scout]:",e),i&&(e.user=i),Object.keys(a).length&&(e.context={...a}),e.breadcrumbs=o.slice(),n.endpoint&&n.sendErrors){let t={"Content-Type":"application/json"};n.token&&(t["X-Ingest-Token"]=n.token),fetch(n.endpoint,{method:"POST",headers:t,body:JSON.stringify(e)}).catch(s=>{console.error("[Scout] Failed to send error:",s.message)})}}function l(e={},t={}){r={...r,...e},n={...n,...t},process.on("uncaughtException",s=>{c({type:"uncaughtException",message:s.message,stack:s.stack,errorTrace:s.stack,timestamp:new Date().toISOString(),...r})}),process.on("unhandledRejection",s=>{c({type:"unhandledRejection",message:s?.message||"Unhandled Promise Rejection",stack:s?.stack||"No stack trace",errorTrace:s?.stack||"No stack trace",timestamp:new Date().toISOString(),...r})})}function m(e,t,s,d){let u={type:"expressError",message:e.message,stack:n.captureStackTrace?e.stack:void 0,errorTrace:n.captureStackTrace?e.stack:void 0,path:t.originalUrl,method:t.method,params:t.params,query:t.query,headers:n.captureRequestDetails?t.headers:void 0,timestamp:new Date().toISOString(),...r};n.captureUserDetails&&t.user&&(u.user={id:t.user.id||t.user._id,email:t.user.email,name:t.user.name||t.user.username}),c(u),s.status(500).json({error:"Internal Server Error"})}function g(e){i=e}function f(e){a={...a,...e}}function k(e,t){a[e]=t}function h(e){o.push({timestamp:Date.now(),...e}),o.length>p&&o.shift()}function S(e,t={}){let s={type:"manual",message:e?.message||String(e),stack:e?.stack,errorTrace:e?.stack,timestamp:new Date().toISOString(),...r};Object.keys(t).length&&(s.context={...a,...t}),c(s)}export{h as addBreadcrumb,S as captureError,m as errorHandlingMiddleware,l as initTracker,f as setContext,k as setTag,g as setUser};
2
2
  //# sourceMappingURL=node.js.map
package/dist/node.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/node.js"],
4
- "sourcesContent": ["/**\n * Scout.js Node.js SDK\n *\n * Captures uncaught exceptions, unhandled rejections, and Express errors.\n *\n * Usage:\n * import { initTracker, errorHandlingMiddleware } from 'scout-error/node'\n */\n\nlet config = {\n debug: false,\n endpoint: '',\n token: null,\n sendErrors: true,\n captureUserDetails: false,\n captureRequestDetails: true,\n captureStackTrace: true,\n}\n\nlet scope = {\n environment: process.env.NODE_ENV || 'production',\n project: null,\n release: null,\n version: null,\n sdk: 'node',\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n}\n\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\nfunction logError(details) {\n if (config.debug) {\n console.error('[Scout]:', details)\n }\n\n // Attach user, context, breadcrumbs\n if (userContext) details.user = userContext\n if (Object.keys(customContext).length) details.context = { ...customContext }\n details.breadcrumbs = breadcrumbs.slice()\n\n if (config.endpoint && config.sendErrors) {\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n fetch(config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(details),\n }).catch(err => {\n console.error('[Scout] Failed to send error:', err.message)\n })\n }\n}\n\n/**\n * Initialize the Node.js error tracker.\n */\nexport function initTracker(customScope = {}, customConfig = {}) {\n scope = { ...scope, ...customScope }\n config = { ...config, ...customConfig }\n\n process.on('uncaughtException', (error) => {\n logError({\n type: 'uncaughtException',\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n\n process.on('unhandledRejection', (reason) => {\n logError({\n type: 'unhandledRejection',\n message: reason?.message || 'Unhandled Promise Rejection',\n stack: reason?.stack || 'No stack trace',\n errorTrace: reason?.stack || 'No stack trace',\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n}\n\n/**\n * Express error handling middleware.\n */\nexport function errorHandlingMiddleware(err, req, res, next) {\n const details = {\n type: 'expressError',\n message: err.message,\n stack: config.captureStackTrace ? err.stack : undefined,\n errorTrace: config.captureStackTrace ? err.stack : undefined,\n path: req.originalUrl,\n method: req.method,\n params: req.params,\n query: req.query,\n headers: config.captureRequestDetails ? req.headers : undefined,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n\n // Auto-capture user from req.user if configured\n if (config.captureUserDetails && req.user) {\n details.user = {\n id: req.user.id || req.user._id,\n email: req.user.email,\n name: req.user.name || req.user.username,\n }\n }\n\n logError(details)\n res.status(500).json({ error: 'Internal Server Error' })\n}\n\n/**\n * Set identified user info.\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context.\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n */\nexport function addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n/**\n * Manually capture an error.\n */\nexport function captureError(error, extra = {}) {\n const details = {\n type: 'manual',\n message: error?.message || String(error),\n stack: error?.stack,\n errorTrace: error?.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n // Put extra fields into context so they show up in the UI\n if (Object.keys(extra).length) {\n details.context = { ...customContext, ...extra }\n }\n logError(details)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Node.js SDK\n *\n * Captures uncaught exceptions, unhandled rejections, and Express errors.\n *\n * Usage:\n * import { initTracker, errorHandlingMiddleware } from 'scout-error/node'\n */\n\nlet config = {\n debug: false,\n endpoint: '',\n token: null,\n sendErrors: true,\n captureUserDetails: false,\n captureRequestDetails: true,\n captureStackTrace: true,\n}\n\nlet scope = {\n environment: process.env.NODE_ENV || 'production',\n project: null,\n release: null,\n version: null,\n sdk: 'node',\n sdkVersion: __SDK_VERSION__,\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n}\n\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\nfunction logError(details) {\n if (config.debug) {\n console.error('[Scout]:', details)\n }\n\n // Attach user, context, breadcrumbs\n if (userContext) details.user = userContext\n if (Object.keys(customContext).length) details.context = { ...customContext }\n details.breadcrumbs = breadcrumbs.slice()\n\n if (config.endpoint && config.sendErrors) {\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n fetch(config.endpoint, {\n method: 'POST',\n headers,\n body: JSON.stringify(details),\n }).catch(err => {\n console.error('[Scout] Failed to send error:', err.message)\n })\n }\n}\n\n/**\n * Initialize the Node.js error tracker.\n */\nexport function initTracker(customScope = {}, customConfig = {}) {\n scope = { ...scope, ...customScope }\n config = { ...config, ...customConfig }\n\n process.on('uncaughtException', (error) => {\n logError({\n type: 'uncaughtException',\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n\n process.on('unhandledRejection', (reason) => {\n logError({\n type: 'unhandledRejection',\n message: reason?.message || 'Unhandled Promise Rejection',\n stack: reason?.stack || 'No stack trace',\n errorTrace: reason?.stack || 'No stack trace',\n timestamp: new Date().toISOString(),\n ...scope,\n })\n })\n}\n\n/**\n * Express error handling middleware.\n */\nexport function errorHandlingMiddleware(err, req, res, next) {\n const details = {\n type: 'expressError',\n message: err.message,\n stack: config.captureStackTrace ? err.stack : undefined,\n errorTrace: config.captureStackTrace ? err.stack : undefined,\n path: req.originalUrl,\n method: req.method,\n params: req.params,\n query: req.query,\n headers: config.captureRequestDetails ? req.headers : undefined,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n\n // Auto-capture user from req.user if configured\n if (config.captureUserDetails && req.user) {\n details.user = {\n id: req.user.id || req.user._id,\n email: req.user.email,\n name: req.user.name || req.user.username,\n }\n }\n\n logError(details)\n res.status(500).json({ error: 'Internal Server Error' })\n}\n\n/**\n * Set identified user info.\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context.\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n */\nexport function addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n/**\n * Manually capture an error.\n */\nexport function captureError(error, extra = {}) {\n const details = {\n type: 'manual',\n message: error?.message || String(error),\n stack: error?.stack,\n errorTrace: error?.stack,\n timestamp: new Date().toISOString(),\n ...scope,\n }\n // Put extra fields into context so they show up in the UI\n if (Object.keys(extra).length) {\n details.context = { ...customContext, ...extra }\n }\n logError(details)\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["config", "scope", "userContext", "customContext", "breadcrumbs", "MAX_BREADCRUMBS", "logError", "details", "headers", "err", "initTracker", "customScope", "customConfig", "error", "reason", "errorHandlingMiddleware", "req", "res", "next", "setUser", "user", "setContext", "ctx", "setTag", "key", "value", "addBreadcrumb", "crumb", "captureError", "extra"]
7
7
  }
package/dist/react.cjs CHANGED
@@ -1,4 +1,4 @@
1
- var v=Object.create;var c=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,b=Object.prototype.hasOwnProperty;var _=(e,r)=>{for(var t in r)c(e,t,{get:r[t],enumerable:!0})},f=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of S(r))!b.call(e,o)&&o!==t&&c(e,o,{get:()=>r[o],enumerable:!(n=y(r,o))||n.enumerable});return e};var T=(e,r,t)=>(t=e!=null?v(k(e)):{},f(r||!e||!e.__esModule?c(t,"default",{value:e,enumerable:!0}):t,e)),I=e=>f(c({},"__esModule",{value:!0}),e);var O={};_(O,{ScoutErrorBoundary:()=>d});module.exports=I(O);var E=T(require("react"),1);var R={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},a={...R},C={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},p={clicks:0,scrolls:0},l=null;var g=null,m={},M=[];var h=console.log;function u(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function x(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",u("user")),localStorage.getItem("__scoutUserId")),r=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",u("session")),sessionStorage.getItem("__scoutSessionId"));return l=l||u("pageload"),{pageloadId:l,userId:e,sessionId:r}}function L(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(t=>e.match(t.p))?.n||"Unknown"}function D(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(t=>e.match(t.p))?.n||"Unknown"}function P(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:L(),browserVersion:window._uaParserResult?.browser?.version||null,os:D(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:p.clicks,userScrolls:p.scrolls}}function U(e,r){let t=new AbortController,n=setTimeout(()=>t.abort(),5e3),o={"Content-Type":"application/json"};return a.token&&(o["X-Ingest-Token"]=a.token),fetch(e,{method:"POST",headers:o,body:JSON.stringify(r),signal:t.signal}).then(s=>(clearTimeout(n),s)).catch(()=>{clearTimeout(n)})}async function A(e){let r=a.browserDetails?P():{},t=Object.assign(e,r,C,x());if(g&&(t.user=g),Object.keys(m).length&&(t.context={...m}),t.breadcrumbs=M.slice(),a.sampleRate&&Math.random()<1-parseFloat(a.sampleRate)){a.debug&&h("[Scout] Suppressed by sampling");return}if(a.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let n=e.errorTrace.split(`
1
+ var v=Object.create;var c=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,_=Object.prototype.hasOwnProperty;var b=(e,r)=>{for(var t in r)c(e,t,{get:r[t],enumerable:!0})},f=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of S(r))!_.call(e,o)&&o!==t&&c(e,o,{get:()=>r[o],enumerable:!(n=y(r,o))||n.enumerable});return e};var I=(e,r,t)=>(t=e!=null?v(k(e)):{},f(r||!e||!e.__esModule?c(t,"default",{value:e,enumerable:!0}):t,e)),T=e=>f(c({},"__esModule",{value:!0}),e);var O={};b(O,{ScoutErrorBoundary:()=>d});module.exports=T(O);var E=I(require("react"),1);var R={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},a={...R},C={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},p={clicks:0,scrolls:0},l=null;var g=null,m={},M=[];var h=console.log;function u(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function x(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",u("user")),localStorage.getItem("__scoutUserId")),r=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",u("session")),sessionStorage.getItem("__scoutSessionId"));return l=l||u("pageload"),{pageloadId:l,userId:e,sessionId:r}}function L(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(t=>e.match(t.p))?.n||"Unknown"}function D(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(t=>e.match(t.p))?.n||"Unknown"}function P(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:L(),browserVersion:window._uaParserResult?.browser?.version||null,os:D(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:p.clicks,userScrolls:p.scrolls}}function U(e,r){let t=new AbortController,n=setTimeout(()=>t.abort(),5e3),o={"Content-Type":"application/json"};return a.token&&(o["X-Ingest-Token"]=a.token),fetch(e,{method:"POST",headers:o,body:JSON.stringify(r),signal:t.signal}).then(s=>(clearTimeout(n),s)).catch(()=>{clearTimeout(n)})}async function A(e){let r=a.browserDetails?P():{},t=Object.assign(e,r,C,x());if(g&&(t.user=g),Object.keys(m).length&&(t.context={...m}),t.breadcrumbs=M.slice(),a.sampleRate&&Math.random()<1-parseFloat(a.sampleRate)){a.debug&&h("[Scout] Suppressed by sampling");return}if(a.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let n=e.errorTrace.split(`
2
2
  `),o=[n[0]];for(let s=1;s<n.length;s++)!n[s].includes("/scout")&&!n[s].includes("scout.js")&&!n[s].includes("scout-error")&&o.push(n[s]);o.length>1&&(e.errorTrace=o.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let n=e.errorTrace||e.stack,o=n?n.split(`
4
4
  `):[];for(let s=1;s<o.length;s++){let i=o[s].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}a.debug&&h("[Scout] Sending:",t),a.endpoint&&U(a.endpoint,t)}function w(e){a.enabled&&A(e)}var d=class extends E.default.Component{constructor(r){super(r),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(r,t){w({message:r.message,stack:r.stack,errorTrace:r.stack,component:t?.componentStack||"",type:"react-error-boundary"})}render(){return this.state.hasError?this.props.fallback||null:this.props.children}};
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/react.js", "../src/index.js"],
4
- "sourcesContent": ["/**\n * Scout.js React Error Boundary\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutErrorBoundary } from 'scoutjs/react'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n *\n * <ScoutErrorBoundary>\n * <App />\n * </ScoutErrorBoundary>\n */\n\nimport React from 'react'\nimport { captureError } from './index.js'\n\nexport class ScoutErrorBoundary extends React.Component {\n constructor(props) {\n super(props)\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError() {\n return { hasError: true }\n }\n\n componentDidCatch(error, errorInfo) {\n captureError({\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n component: errorInfo?.componentStack || '',\n type: 'react-error-boundary',\n })\n }\n\n render() {\n if (this.state.hasError) {\n return this.props.fallback || null\n }\n return this.props.children\n }\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js React Error Boundary\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutErrorBoundary } from 'scoutjs/react'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n *\n * <ScoutErrorBoundary>\n * <App />\n * </ScoutErrorBoundary>\n */\n\nimport React from 'react'\nimport { captureError } from './index.js'\n\nexport class ScoutErrorBoundary extends React.Component {\n constructor(props) {\n super(props)\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError() {\n return { hasError: true }\n }\n\n componentDidCatch(error, errorInfo) {\n captureError({\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n component: errorInfo?.componentStack || '',\n type: 'react-error-boundary',\n })\n }\n\n render() {\n if (this.state.hasError) {\n return this.props.fallback || null\n }\n return this.props.children\n }\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["react_exports", "__export", "ScoutErrorBoundary", "__toCommonJS", "import_react", "defaultConfig", "config", "scope", "userInteractions", "pageloadId", "userContext", "customContext", "breadcrumbs", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "o", "captureBrowserDetails", "conn", "userInteractions", "postData", "url", "data", "controller", "timeout", "headers", "config", "r", "pushErrorEvent", "obj", "details", "config", "captureBrowserDetails", "event", "scope", "getIds", "userContext", "customContext", "breadcrumbs", "_consoleLog", "lines", "filtered", "i", "stack", "match", "postData", "captureError", "ScoutErrorBoundary", "React", "props", "error", "errorInfo", "captureError"]
7
7
  }
package/dist/react.js CHANGED
@@ -1,5 +1,5 @@
1
- import T from"react";var h={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},s={...h},w={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},u={clicks:0,scrolls:0},c=null;var d=null,f={},E=[];var p=console.log;function l(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function v(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",l("user")),localStorage.getItem("__scoutUserId")),n=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",l("session")),sessionStorage.getItem("__scoutSessionId"));return c=c||l("pageload"),{pageloadId:c,userId:e,sessionId:n}}function y(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(r=>e.match(r.p))?.n||"Unknown"}function S(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(r=>e.match(r.p))?.n||"Unknown"}function k(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:y(),browserVersion:window._uaParserResult?.browser?.version||null,os:S(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:u.clicks,userScrolls:u.scrolls}}function b(e,n){let r=new AbortController,t=setTimeout(()=>r.abort(),5e3),a={"Content-Type":"application/json"};return s.token&&(a["X-Ingest-Token"]=s.token),fetch(e,{method:"POST",headers:a,body:JSON.stringify(n),signal:r.signal}).then(o=>(clearTimeout(t),o)).catch(()=>{clearTimeout(t)})}async function _(e){let n=s.browserDetails?k():{},r=Object.assign(e,n,w,v());if(d&&(r.user=d),Object.keys(f).length&&(r.context={...f}),r.breadcrumbs=E.slice(),s.sampleRate&&Math.random()<1-parseFloat(s.sampleRate)){s.debug&&p("[Scout] Suppressed by sampling");return}if(s.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let t=e.errorTrace.split(`
1
+ import I from"react";var h={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},s={...h},w={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},u={clicks:0,scrolls:0},c=null;var d=null,f={},E=[];var p=console.log;function l(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function v(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",l("user")),localStorage.getItem("__scoutUserId")),n=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",l("session")),sessionStorage.getItem("__scoutSessionId"));return c=c||l("pageload"),{pageloadId:c,userId:e,sessionId:n}}function y(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(r=>e.match(r.p))?.n||"Unknown"}function S(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(r=>e.match(r.p))?.n||"Unknown"}function k(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:y(),browserVersion:window._uaParserResult?.browser?.version||null,os:S(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:u.clicks,userScrolls:u.scrolls}}function _(e,n){let r=new AbortController,t=setTimeout(()=>r.abort(),5e3),a={"Content-Type":"application/json"};return s.token&&(a["X-Ingest-Token"]=s.token),fetch(e,{method:"POST",headers:a,body:JSON.stringify(n),signal:r.signal}).then(o=>(clearTimeout(t),o)).catch(()=>{clearTimeout(t)})}async function b(e){let n=s.browserDetails?k():{},r=Object.assign(e,n,w,v());if(d&&(r.user=d),Object.keys(f).length&&(r.context={...f}),r.breadcrumbs=E.slice(),s.sampleRate&&Math.random()<1-parseFloat(s.sampleRate)){s.debug&&p("[Scout] Suppressed by sampling");return}if(s.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let t=e.errorTrace.split(`
2
2
  `),a=[t[0]];for(let o=1;o<t.length;o++)!t[o].includes("/scout")&&!t[o].includes("scout.js")&&!t[o].includes("scout-error")&&a.push(t[o]);a.length>1&&(e.errorTrace=a.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let t=e.errorTrace||e.stack,a=t?t.split(`
4
- `):[];for(let o=1;o<a.length;o++){let i=a[o].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}s.debug&&p("[Scout] Sending:",r),s.endpoint&&b(s.endpoint,r)}function g(e){s.enabled&&_(e)}var m=class extends T.Component{constructor(n){super(n),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(n,r){g({message:n.message,stack:n.stack,errorTrace:n.stack,component:r?.componentStack||"",type:"react-error-boundary"})}render(){return this.state.hasError?this.props.fallback||null:this.props.children}};export{m as ScoutErrorBoundary};
4
+ `):[];for(let o=1;o<a.length;o++){let i=a[o].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}s.debug&&p("[Scout] Sending:",r),s.endpoint&&_(s.endpoint,r)}function g(e){s.enabled&&b(e)}var m=class extends I.Component{constructor(n){super(n),this.state={hasError:!1}}static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(n,r){g({message:n.message,stack:n.stack,errorTrace:n.stack,component:r?.componentStack||"",type:"react-error-boundary"})}render(){return this.state.hasError?this.props.fallback||null:this.props.children}};export{m as ScoutErrorBoundary};
5
5
  //# sourceMappingURL=react.js.map
package/dist/react.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/react.js", "../src/index.js"],
4
- "sourcesContent": ["/**\n * Scout.js React Error Boundary\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutErrorBoundary } from 'scoutjs/react'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n *\n * <ScoutErrorBoundary>\n * <App />\n * </ScoutErrorBoundary>\n */\n\nimport React from 'react'\nimport { captureError } from './index.js'\n\nexport class ScoutErrorBoundary extends React.Component {\n constructor(props) {\n super(props)\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError() {\n return { hasError: true }\n }\n\n componentDidCatch(error, errorInfo) {\n captureError({\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n component: errorInfo?.componentStack || '',\n type: 'react-error-boundary',\n })\n }\n\n render() {\n if (this.state.hasError) {\n return this.props.fallback || null\n }\n return this.props.children\n }\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js React Error Boundary\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutErrorBoundary } from 'scoutjs/react'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n *\n * <ScoutErrorBoundary>\n * <App />\n * </ScoutErrorBoundary>\n */\n\nimport React from 'react'\nimport { captureError } from './index.js'\n\nexport class ScoutErrorBoundary extends React.Component {\n constructor(props) {\n super(props)\n this.state = { hasError: false }\n }\n\n static getDerivedStateFromError() {\n return { hasError: true }\n }\n\n componentDidCatch(error, errorInfo) {\n captureError({\n message: error.message,\n stack: error.stack,\n errorTrace: error.stack,\n component: errorInfo?.componentStack || '',\n type: 'react-error-boundary',\n })\n }\n\n render() {\n if (this.state.hasError) {\n return this.props.fallback || null\n }\n return this.props.children\n }\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["React", "defaultConfig", "config", "scope", "userInteractions", "pageloadId", "userContext", "customContext", "breadcrumbs", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "o", "captureBrowserDetails", "conn", "userInteractions", "postData", "url", "data", "controller", "timeout", "headers", "config", "r", "pushErrorEvent", "obj", "details", "config", "captureBrowserDetails", "event", "scope", "getIds", "userContext", "customContext", "breadcrumbs", "_consoleLog", "lines", "filtered", "i", "stack", "match", "postData", "captureError", "ScoutErrorBoundary", "React", "props", "error", "errorInfo", "captureError"]
7
7
  }
package/dist/vue.cjs CHANGED
@@ -1,4 +1,4 @@
1
- var c=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var v=(e,r)=>{for(var n in r)c(e,n,{get:r[n],enumerable:!0})},E=(e,r,n,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of h(r))!y.call(e,o)&&o!==n&&c(e,o,{get:()=>r[o],enumerable:!(t=w(r,o))||t.enumerable});return e};var S=e=>E(c({},"__esModule",{value:!0}),e);var P={};v(P,{ScoutVue:()=>L});module.exports=S(P);var _={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},a={..._},k={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},f={clicks:0,scrolls:0},l=null;var g=null,p={},b=[];var m=console.log;function u(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function T(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",u("user")),localStorage.getItem("__scoutUserId")),r=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",u("session")),sessionStorage.getItem("__scoutSessionId"));return l=l||u("pageload"),{pageloadId:l,userId:e,sessionId:r}}function I(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(n=>e.match(n.p))?.n||"Unknown"}function R(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(n=>e.match(n.p))?.n||"Unknown"}function C(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:I(),browserVersion:window._uaParserResult?.browser?.version||null,os:R(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:f.clicks,userScrolls:f.scrolls}}function M(e,r){let n=new AbortController,t=setTimeout(()=>n.abort(),5e3),o={"Content-Type":"application/json"};return a.token&&(o["X-Ingest-Token"]=a.token),fetch(e,{method:"POST",headers:o,body:JSON.stringify(r),signal:n.signal}).then(s=>(clearTimeout(t),s)).catch(()=>{clearTimeout(t)})}async function x(e){let r=a.browserDetails?C():{},n=Object.assign(e,r,k,T());if(g&&(n.user=g),Object.keys(p).length&&(n.context={...p}),n.breadcrumbs=b.slice(),a.sampleRate&&Math.random()<1-parseFloat(a.sampleRate)){a.debug&&m("[Scout] Suppressed by sampling");return}if(a.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let t=e.errorTrace.split(`
1
+ var c=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var v=(e,r)=>{for(var n in r)c(e,n,{get:r[n],enumerable:!0})},E=(e,r,n,t)=>{if(r&&typeof r=="object"||typeof r=="function")for(let o of h(r))!y.call(e,o)&&o!==n&&c(e,o,{get:()=>r[o],enumerable:!(t=w(r,o))||t.enumerable});return e};var S=e=>E(c({},"__esModule",{value:!0}),e);var P={};v(P,{ScoutVue:()=>L});module.exports=S(P);var _={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},a={..._},k={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},f={clicks:0,scrolls:0},l=null;var g=null,p={},b=[];var m=console.log;function u(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function T(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",u("user")),localStorage.getItem("__scoutUserId")),r=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",u("session")),sessionStorage.getItem("__scoutSessionId"));return l=l||u("pageload"),{pageloadId:l,userId:e,sessionId:r}}function I(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(n=>e.match(n.p))?.n||"Unknown"}function R(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(n=>e.match(n.p))?.n||"Unknown"}function C(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:I(),browserVersion:window._uaParserResult?.browser?.version||null,os:R(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:f.clicks,userScrolls:f.scrolls}}function M(e,r){let n=new AbortController,t=setTimeout(()=>n.abort(),5e3),o={"Content-Type":"application/json"};return a.token&&(o["X-Ingest-Token"]=a.token),fetch(e,{method:"POST",headers:o,body:JSON.stringify(r),signal:n.signal}).then(s=>(clearTimeout(t),s)).catch(()=>{clearTimeout(t)})}async function x(e){let r=a.browserDetails?C():{},n=Object.assign(e,r,k,T());if(g&&(n.user=g),Object.keys(p).length&&(n.context={...p}),n.breadcrumbs=b.slice(),a.sampleRate&&Math.random()<1-parseFloat(a.sampleRate)){a.debug&&m("[Scout] Suppressed by sampling");return}if(a.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let t=e.errorTrace.split(`
2
2
  `),o=[t[0]];for(let s=1;s<t.length;s++)!t[s].includes("/scout")&&!t[s].includes("scout.js")&&!t[s].includes("scout-error")&&o.push(t[s]);o.length>1&&(e.errorTrace=o.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let t=e.errorTrace||e.stack,o=t?t.split(`
4
4
  `):[];for(let s=1;s<o.length;s++){let i=o[s].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}a.debug&&m("[Scout] Sending:",n),a.endpoint&&M(a.endpoint,n)}function d(e){a.enabled&&x(e)}var L={install(e){e.config.errorHandler=(r,n,t)=>{d({message:r.message,stack:r.stack,errorTrace:r.stack,component:n?.$options?.name||n?.$options?.__name||"Anonymous",type:"vue-error-handler",info:t})},e.config.warnHandler=(r,n,t)=>{d({message:r,component:n?.$options?.name||n?.$options?.__name||"Anonymous",type:"vue-warn-handler",errorTrace:t})}}};
package/dist/vue.cjs.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/vue.js", "../src/index.js"],
4
- "sourcesContent": ["/**\n * Scout.js Vue Plugin\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutVue } from 'scoutjs/vue'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n * app.use(ScoutVue)\n */\n\nimport { captureError } from './index.js'\n\n/**\n * Vue plugin that installs error and warning handlers.\n *\n * app.use(ScoutVue)\n */\nexport const ScoutVue = {\n install(app) {\n app.config.errorHandler = (err, vm, info) => {\n captureError({\n message: err.message,\n stack: err.stack,\n errorTrace: err.stack,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-error-handler',\n info,\n })\n }\n\n app.config.warnHandler = (msg, vm, trace) => {\n captureError({\n message: msg,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-warn-handler',\n errorTrace: trace,\n })\n }\n },\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Vue Plugin\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutVue } from 'scoutjs/vue'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n * app.use(ScoutVue)\n */\n\nimport { captureError } from './index.js'\n\n/**\n * Vue plugin that installs error and warning handlers.\n *\n * app.use(ScoutVue)\n */\nexport const ScoutVue = {\n install(app) {\n app.config.errorHandler = (err, vm, info) => {\n captureError({\n message: err.message,\n stack: err.stack,\n errorTrace: err.stack,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-error-handler',\n info,\n })\n }\n\n app.config.warnHandler = (msg, vm, trace) => {\n captureError({\n message: msg,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-warn-handler',\n errorTrace: trace,\n })\n }\n },\n}\n", "/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["vue_exports", "__export", "ScoutVue", "__toCommonJS", "defaultConfig", "config", "scope", "userInteractions", "pageloadId", "userContext", "customContext", "breadcrumbs", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "o", "captureBrowserDetails", "conn", "userInteractions", "postData", "url", "data", "controller", "timeout", "headers", "config", "r", "pushErrorEvent", "obj", "details", "config", "captureBrowserDetails", "event", "scope", "getIds", "userContext", "customContext", "breadcrumbs", "_consoleLog", "lines", "filtered", "i", "stack", "match", "postData", "captureError", "ScoutVue", "app", "err", "vm", "info", "captureError", "msg", "trace"]
7
7
  }
package/dist/vue.js CHANGED
@@ -1,4 +1,4 @@
1
- var m={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},s={...m},w={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",project:null,release:null,version:null,app:null},d={clicks:0,scrolls:0},c=null;var f=null,g={},h=[];var p=console.log;function l(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function y(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",l("user")),localStorage.getItem("__scoutUserId")),t=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",l("session")),sessionStorage.getItem("__scoutSessionId"));return c=c||l("pageload"),{pageloadId:c,userId:e,sessionId:t}}function v(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(r=>e.match(r.p))?.n||"Unknown"}function E(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(r=>e.match(r.p))?.n||"Unknown"}function S(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:v(),browserVersion:window._uaParserResult?.browser?.version||null,os:E(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:d.clicks,userScrolls:d.scrolls}}function _(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),5e3),a={"Content-Type":"application/json"};return s.token&&(a["X-Ingest-Token"]=s.token),fetch(e,{method:"POST",headers:a,body:JSON.stringify(t),signal:r.signal}).then(o=>(clearTimeout(n),o)).catch(()=>{clearTimeout(n)})}async function k(e){let t=s.browserDetails?S():{},r=Object.assign(e,t,w,y());if(f&&(r.user=f),Object.keys(g).length&&(r.context={...g}),r.breadcrumbs=h.slice(),s.sampleRate&&Math.random()<1-parseFloat(s.sampleRate)){s.debug&&p("[Scout] Suppressed by sampling");return}if(s.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let n=e.errorTrace.split(`
1
+ var m={trackUserInteractions:!0,selfHealingErrors:!1,attachStacktrace:!0,handleSourceMaps:!1,browserDetails:!0,warnOnCapture:!1,loadUAParser:!0,ignoreErrors:null,sendErrors:!0,sampleRate:1,enabled:!0,debug:!1,endpoint:"",token:null,overrideOnError:!1,overrideOnUnhandledRejection:!1,addErrorEventListener:!0,addUnhandledRejectionEventListener:!0,overrideConsoleLog:!1,overrideConsoleWarn:!1,overrideConsoleInfo:!1,overrideConsoleError:!0},s={...m},w={environment:typeof window<"u"&&window.location?.hostname==="localhost"?"development":"production",sdk:"javascript",sdkVersion:"0.2.3",project:null,release:null,version:null,app:null},d={clicks:0,scrolls:0},c=null;var f=null,g={},h=[];var p=console.log;function l(e){return`${e}_${Math.random().toString(36).substr(2,9)}`}function y(){let e=localStorage.getItem("__scoutUserId")||(localStorage.setItem("__scoutUserId",l("user")),localStorage.getItem("__scoutUserId")),t=sessionStorage.getItem("__scoutSessionId")||(sessionStorage.setItem("__scoutSessionId",l("session")),sessionStorage.getItem("__scoutSessionId"));return c=c||l("pageload"),{pageloadId:c,userId:e,sessionId:t}}function v(){if(window._uaParserResult?.browser?.name)return window._uaParserResult.browser.name;let e=navigator.userAgent;return[{p:/Chrome.*Mobile/,n:"Chrome Mobile"},{p:/Chrome/,n:"Chrome"},{p:/Firefox.*Mobile/,n:"Firefox Mobile"},{p:/Firefox/,n:"Firefox"},{p:/Safari.*Mobile/,n:"Safari Mobile"},{p:/Safari/,n:"Safari"},{p:/MSIE|Trident/,n:"Internet Explorer"},{p:/Edge/,n:"Edge"}].find(r=>e.match(r.p))?.n||"Unknown"}function E(){if(window._uaParserResult?.os?.name)return window._uaParserResult.os.name;let e=navigator.userAgent;return[{p:/Win/,n:"Windows"},{p:/Mac/,n:"Mac OS"},{p:/X11|Linux/,n:"Linux"},{p:/Android/,n:"Android"},{p:/iPhone|iPad/,n:"iOS"}].find(r=>e.match(r.p))?.n||"Unknown"}function S(){let e=navigator.connection||navigator.mozConnection||navigator.webkitConnection;return{connectionType:e?e.effectiveType:"unknown",userAgent:navigator.userAgent,width:window.innerWidth,height:window.innerHeight,screenWidth:screen.width,screenHeight:screen.height,errorTimestamp:Date.now(),timeLocale:Intl.DateTimeFormat().resolvedOptions().timeZone,browserLocale:navigator.language||navigator.userLanguage,sessionTime:Math.round(performance.now()/1e3),deviceMemory:navigator.deviceMemory||"unknown",timezoneOffset:new Date().getTimezoneOffset(),cookiesEnabled:navigator.cookieEnabled,url:window.location.href,host:window.location.host,referrer:document.referrer,browser:v(),browserVersion:window._uaParserResult?.browser?.version||null,os:E(),osVersion:window._uaParserResult?.os?.version||null,deviceType:window._uaParserResult?.device?.type||null,deviceModel:window._uaParserResult?.device?.model||null,deviceVendor:window._uaParserResult?.device?.vendor||null,loadTime:Math.max(0,performance.timing.loadEventEnd-performance.timing.navigationStart),userClicks:d.clicks,userScrolls:d.scrolls}}function _(e,t){let r=new AbortController,n=setTimeout(()=>r.abort(),5e3),a={"Content-Type":"application/json"};return s.token&&(a["X-Ingest-Token"]=s.token),fetch(e,{method:"POST",headers:a,body:JSON.stringify(t),signal:r.signal}).then(o=>(clearTimeout(n),o)).catch(()=>{clearTimeout(n)})}async function k(e){let t=s.browserDetails?S():{},r=Object.assign(e,t,w,y());if(f&&(r.user=f),Object.keys(g).length&&(r.context={...g}),r.breadcrumbs=h.slice(),s.sampleRate&&Math.random()<1-parseFloat(s.sampleRate)){s.debug&&p("[Scout] Suppressed by sampling");return}if(s.attachStacktrace||(e.errorTrace=null),e.errorTrace)try{let n=e.errorTrace.split(`
2
2
  `),a=[n[0]];for(let o=1;o<n.length;o++)!n[o].includes("/scout")&&!n[o].includes("scout.js")&&!n[o].includes("scout-error")&&a.push(n[o]);a.length>1&&(e.errorTrace=a.join(`
3
3
  `))}catch{}if((e.errorTrace||e.stack)&&!e.source)try{let n=e.errorTrace||e.stack,a=n?n.split(`
4
4
  `):[];for(let o=1;o<a.length;o++){let i=a[o].trim().match(/(http.*?):(\d+):(\d+)/);if(i){e.source=i[1],e.lineno=parseInt(i[2],10),e.colno=parseInt(i[3],10);break}}}catch{}s.debug&&p("[Scout] Sending:",r),s.endpoint&&_(s.endpoint,r)}function u(e){s.enabled&&k(e)}var I={install(e){e.config.errorHandler=(t,r,n)=>{u({message:t.message,stack:t.stack,errorTrace:t.stack,component:r?.$options?.name||r?.$options?.__name||"Anonymous",type:"vue-error-handler",info:n})},e.config.warnHandler=(t,r,n)=>{u({message:t,component:r?.$options?.name||r?.$options?.__name||"Anonymous",type:"vue-warn-handler",errorTrace:n})}}};export{I as ScoutVue};
package/dist/vue.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.js", "../src/vue.js"],
4
- "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n", "/**\n * Scout.js Vue Plugin\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutVue } from 'scoutjs/vue'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n * app.use(ScoutVue)\n */\n\nimport { captureError } from './index.js'\n\n/**\n * Vue plugin that installs error and warning handlers.\n *\n * app.use(ScoutVue)\n */\nexport const ScoutVue = {\n install(app) {\n app.config.errorHandler = (err, vm, info) => {\n captureError({\n message: err.message,\n stack: err.stack,\n errorTrace: err.stack,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-error-handler',\n info,\n })\n }\n\n app.config.warnHandler = (msg, vm, trace) => {\n captureError({\n message: msg,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-warn-handler',\n errorTrace: trace,\n })\n }\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Scout.js Browser SDK\n *\n * Captures errors, unhandled rejections, and console output.\n * Collects browser telemetry, session tracking, and source maps.\n *\n * Usage:\n * import { init, captureError } from 'scout-error'\n * init({ app: 'My App', project: 'my-project' }, { endpoint: 'https://...' })\n */\n\nconst defaultConfig = {\n trackUserInteractions: true,\n selfHealingErrors: false,\n attachStacktrace: true,\n handleSourceMaps: false,\n browserDetails: true,\n warnOnCapture: false,\n loadUAParser: true,\n ignoreErrors: null,\n sendErrors: true,\n sampleRate: 1.0,\n enabled: true,\n debug: false,\n endpoint: '',\n token: null,\n\n overrideOnError: false,\n overrideOnUnhandledRejection: false,\n addErrorEventListener: true,\n addUnhandledRejectionEventListener: true,\n\n overrideConsoleLog: false,\n overrideConsoleWarn: false,\n overrideConsoleInfo: false,\n overrideConsoleError: true,\n}\n\nlet config = { ...defaultConfig }\n\nlet scope = {\n environment: typeof window !== 'undefined' && window.location?.hostname === 'localhost' ? 'development' : 'production',\n sdk: 'javascript',\n sdkVersion: __SDK_VERSION__,\n project: null,\n release: null,\n version: null,\n app: null,\n}\n\nconst userInteractions = { clicks: 0, scrolls: 0 }\nlet pageloadId = null\nlet initialized = false\nlet userContext = null\nlet customContext = {}\nconst breadcrumbs = []\nconst MAX_BREADCRUMBS = 30\n\n// Save originals before any overrides\nconst _consoleError = console.error\nconst _consoleWarn = console.warn\nconst _consoleInfo = console.info\nconst _consoleLog = console.log\n\n// --- Utilities ---\n\nfunction generateId(prefix) {\n return `${prefix}_${Math.random().toString(36).substr(2, 9)}`\n}\n\nfunction getIds() {\n const userId = localStorage.getItem('__scoutUserId') || (localStorage.setItem('__scoutUserId', generateId('user')), localStorage.getItem('__scoutUserId'))\n const sessionId = sessionStorage.getItem('__scoutSessionId') || (sessionStorage.setItem('__scoutSessionId', generateId('session')), sessionStorage.getItem('__scoutSessionId'))\n pageloadId = pageloadId || generateId('pageload')\n return { pageloadId, userId, sessionId }\n}\n\nfunction getBrowser() {\n if (window._uaParserResult?.browser?.name) return window._uaParserResult.browser.name\n const ua = navigator.userAgent\n const map = [\n { p: /Chrome.*Mobile/, n: 'Chrome Mobile' },\n { p: /Chrome/, n: 'Chrome' },\n { p: /Firefox.*Mobile/, n: 'Firefox Mobile' },\n { p: /Firefox/, n: 'Firefox' },\n { p: /Safari.*Mobile/, n: 'Safari Mobile' },\n { p: /Safari/, n: 'Safari' },\n { p: /MSIE|Trident/, n: 'Internet Explorer' },\n { p: /Edge/, n: 'Edge' },\n ]\n return map.find(b => ua.match(b.p))?.n || 'Unknown'\n}\n\nfunction getOS() {\n if (window._uaParserResult?.os?.name) return window._uaParserResult.os.name\n const ua = navigator.userAgent\n const map = [\n { p: /Win/, n: 'Windows' },\n { p: /Mac/, n: 'Mac OS' },\n { p: /X11|Linux/, n: 'Linux' },\n { p: /Android/, n: 'Android' },\n { p: /iPhone|iPad/, n: 'iOS' },\n ]\n return map.find(o => ua.match(o.p))?.n || 'Unknown'\n}\n\nfunction captureBrowserDetails() {\n const conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection\n return {\n connectionType: conn ? conn.effectiveType : 'unknown',\n userAgent: navigator.userAgent,\n width: window.innerWidth,\n height: window.innerHeight,\n screenWidth: screen.width,\n screenHeight: screen.height,\n errorTimestamp: Date.now(),\n timeLocale: Intl.DateTimeFormat().resolvedOptions().timeZone,\n browserLocale: navigator.language || navigator.userLanguage,\n sessionTime: Math.round(performance.now() / 1000),\n deviceMemory: navigator.deviceMemory || 'unknown',\n timezoneOffset: new Date().getTimezoneOffset(),\n cookiesEnabled: navigator.cookieEnabled,\n url: window.location.href,\n host: window.location.host,\n referrer: document.referrer,\n browser: getBrowser(),\n browserVersion: window._uaParserResult?.browser?.version || null,\n os: getOS(),\n osVersion: window._uaParserResult?.os?.version || null,\n deviceType: window._uaParserResult?.device?.type || null,\n deviceModel: window._uaParserResult?.device?.model || null,\n deviceVendor: window._uaParserResult?.device?.vendor || null,\n loadTime: Math.max(0, performance.timing.loadEventEnd - performance.timing.navigationStart),\n userClicks: userInteractions.clicks,\n userScrolls: userInteractions.scrolls,\n }\n}\n\nfunction shouldIgnoreError(msg) {\n if (!config.ignoreErrors || !Array.isArray(config.ignoreErrors)) return false\n return config.ignoreErrors.some(pattern => {\n if (typeof pattern === 'string') return msg.includes(pattern)\n if (pattern instanceof RegExp) return pattern.test(msg)\n return false\n })\n}\n\nfunction postData(url, data) {\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), 5000)\n\n const headers = { 'Content-Type': 'application/json' }\n if (config.token) headers['X-Ingest-Token'] = config.token\n\n return fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(data),\n signal: controller.signal,\n })\n .then(r => { clearTimeout(timeout); return r })\n .catch(() => { clearTimeout(timeout) })\n}\n\nfunction argsToString(args) {\n const fmt = (args[0] || '') + ''\n const rest = [...args]\n return fmt.replace(/%[sdj]/g, (m) => {\n const v = rest.shift()\n if (m === '%s') return String(v)\n if (m === '%d') return Number(v)\n if (m === '%j') return JSON.stringify(v)\n return m\n })\n}\n\n// --- Breadcrumbs ---\n\nfunction _addBreadcrumb(crumb) {\n breadcrumbs.push({ timestamp: Date.now(), ...crumb })\n if (breadcrumbs.length > MAX_BREADCRUMBS) breadcrumbs.shift()\n}\n\n// --- Core ---\n\nasync function pushErrorEvent(obj) {\n const details = config.browserDetails ? captureBrowserDetails() : {}\n const event = Object.assign(obj, details, scope, getIds())\n\n if (userContext) event.user = userContext\n if (Object.keys(customContext).length) event.context = { ...customContext }\n event.breadcrumbs = breadcrumbs.slice()\n\n if (config.sampleRate && Math.random() < (1 - parseFloat(config.sampleRate))) {\n if (config.debug) _consoleLog('[Scout] Suppressed by sampling')\n return\n }\n\n if (!config.attachStacktrace) obj.errorTrace = null\n\n // Strip scout's own frames from stack traces (for console.error/warn captures)\n if (obj.errorTrace) {\n try {\n const lines = obj.errorTrace.split('\\n')\n const filtered = [lines[0]]\n for (let i = 1; i < lines.length; i++) {\n if (!lines[i].includes('/scout') && !lines[i].includes('scout.js') && !lines[i].includes('scout-error')) {\n filtered.push(lines[i])\n }\n }\n if (filtered.length > 1) obj.errorTrace = filtered.join('\\n')\n } catch (e) { /* ignore */ }\n }\n\n if ((obj.errorTrace || obj.stack) && !obj.source) {\n try {\n const stack = obj.errorTrace || obj.stack\n const lines = stack ? stack.split('\\n') : []\n // Find the first frame with a source location (skip the error message line)\n for (let i = 1; i < lines.length; i++) {\n const match = lines[i].trim().match(/(http.*?):(\\d+):(\\d+)/)\n if (match) {\n obj.source = match[1]\n obj.lineno = parseInt(match[2], 10)\n obj.colno = parseInt(match[3], 10)\n break\n }\n }\n } catch (e) { /* ignore */ }\n }\n\n if (config.debug) _consoleLog('[Scout] Sending:', event)\n if (config.endpoint) postData(config.endpoint, event)\n}\n\n/**\n * Manually capture an error object.\n */\nexport function captureError(event) {\n if (!config.enabled) return\n pushErrorEvent(event)\n}\n\n/**\n * Set identified user info. Call after login.\n * @param {{ id?: string, email?: string, name?: string }} user\n */\nexport function setUser(user) {\n userContext = user\n}\n\n/**\n * Merge custom key-value context attached to all future errors.\n * @param {Object} ctx\n */\nexport function setContext(ctx) {\n customContext = { ...customContext, ...ctx }\n}\n\n/**\n * Set a single context tag.\n */\nexport function setTag(key, value) {\n customContext[key] = value\n}\n\n/**\n * Manually add a breadcrumb.\n * @param {{ category?: string, message?: string, data?: Object }} crumb\n */\nexport function addBreadcrumb(crumb) {\n _addBreadcrumb(crumb)\n}\n\n// --- Setup ---\n\nfunction setupListeners() {\n // Click tracking + breadcrumbs\n if (config.trackUserInteractions) {\n document.addEventListener('click', (e) => {\n userInteractions.clicks++\n const el = e.target\n const tag = el.tagName ? el.tagName.toLowerCase() : ''\n const text = (el.textContent || '').trim().slice(0, 50)\n _addBreadcrumb({ category: 'click', message: tag + (text ? ': ' + text : '') })\n })\n let lastScroll = 0\n window.addEventListener('scroll', () => {\n const now = Date.now()\n if (now - lastScroll > 100) { userInteractions.scrolls++; lastScroll = now }\n })\n }\n\n // Navigation breadcrumbs\n const origPushState = history.pushState\n history.pushState = function() {\n origPushState.apply(this, arguments)\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n }\n window.addEventListener('popstate', () => {\n _addBreadcrumb({ category: 'navigation', message: window.location.href })\n })\n\n // Fetch breadcrumbs\n const origFetch = window.fetch\n window.fetch = function(input, init) {\n const url = typeof input === 'string' ? input : (input?.url || '')\n const method = init?.method || 'GET'\n const start = Date.now()\n return origFetch.apply(this, arguments).then(response => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { status: response.status, duration: Date.now() - start } })\n return response\n }).catch(err => {\n _addBreadcrumb({ category: 'fetch', message: `${method} ${url}`, data: { error: err.message, duration: Date.now() - start } })\n throw err\n })\n }\n\n // XHR breadcrumbs\n const origOpen = XMLHttpRequest.prototype.open\n const origSend = XMLHttpRequest.prototype.send\n XMLHttpRequest.prototype.open = function(method, url) {\n this._scoutMethod = method\n this._scoutUrl = url\n return origOpen.apply(this, arguments)\n }\n XMLHttpRequest.prototype.send = function() {\n const self = this\n const start = Date.now()\n self.addEventListener('loadend', () => {\n _addBreadcrumb({ category: 'xhr', message: `${self._scoutMethod || 'GET'} ${self._scoutUrl || ''}`, data: { status: self.status, duration: Date.now() - start } })\n })\n return origSend.apply(this, arguments)\n }\n\n // Error event listener\n if (config.addErrorEventListener) {\n window.addEventListener('error', async (event) => {\n if (!config.enabled) return\n try {\n const errorTrace = event.error ? event.error.stack : 'No stack trace available'\n if (shouldIgnoreError(event.message)) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'window.onerror',\n message: event.message,\n source: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Error handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Unhandled rejection listener\n if (config.addUnhandledRejectionEventListener) {\n window.addEventListener('unhandledrejection', (event) => {\n if (!config.enabled) return\n try {\n const error = event.reason\n const errorTrace = error?.stack || 'No stack trace available'\n if (shouldIgnoreError(error?.message || '')) return\n if (config.sendErrors) {\n pushErrorEvent({\n type: 'Unhandled Promise Rejection',\n message: error?.message || 'Unhandled Promise Rejection',\n reason: event.reason,\n errorTrace,\n })\n }\n } catch (e) {\n _consoleWarn('[Scout] Rejection handler failure:', e)\n }\n if (config.selfHealingErrors) event.preventDefault()\n })\n }\n\n // Console overrides\n if (config.overrideConsoleError) {\n console.error = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.error', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.error override failure:', e) }\n }\n }\n\n if (config.overrideConsoleWarn) {\n console.warn = function (...args) {\n if (!config.enabled) return\n try {\n const errorTrace = new Error().stack\n if (shouldIgnoreError(argsToString(args))) return\n if (config.sendErrors) pushErrorEvent({ type: 'console.warn', errorTrace, args: argsToString(args) })\n } catch (e) { _consoleWarn('[Scout] console.warn override failure:', e) }\n }\n }\n\n // Load UA parser\n if (config.loadUAParser && config.browserDetails) {\n const s = document.createElement('script')\n s.src = 'https://cdn.jsdelivr.net/npm/ua-parser-js/dist/ua-parser.min.js'\n s.async = true\n s.onload = () => {\n if (typeof UAParser !== 'undefined') {\n window._uaParserResult = new UAParser().getResult()\n }\n }\n document.head.appendChild(s)\n }\n}\n\n/**\n * Initialize Scout error tracking.\n *\n * @param {Object} scopeOptions - { app, project, version, environment, user }\n * @param {Object} configOptions - { endpoint, token, sampleRate, debug, ... }\n */\nexport function init(scopeOptions = {}, configOptions = {}) {\n // Extract user from scope if provided\n if (scopeOptions.user) {\n userContext = scopeOptions.user\n delete scopeOptions.user\n }\n\n if (initialized) {\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n return\n }\n\n scope = { ...scope, ...scopeOptions }\n config = { ...config, ...configOptions }\n initialized = true\n\n if (typeof window !== 'undefined') {\n setupListeners()\n\n window.Scout = {\n init: (s, c) => { if (s?.user) { userContext = s.user; delete s.user }; scope = { ...scope, ...s }; if (c) config = { ...config, ...c } },\n setScope: (s) => { scope = { ...scope, ...s } },\n setConfig: (c) => { config = { ...config, ...c } },\n setUser,\n setContext,\n setTag,\n addBreadcrumb: _addBreadcrumb,\n error: captureError,\n }\n }\n}\n", "/**\n * Scout.js Vue Plugin\n *\n * Usage:\n * import { init } from 'scoutjs'\n * import { ScoutVue } from 'scoutjs/vue'\n *\n * init({ app: 'My App', project: 'my-project' }, { endpoint: '...' })\n * app.use(ScoutVue)\n */\n\nimport { captureError } from './index.js'\n\n/**\n * Vue plugin that installs error and warning handlers.\n *\n * app.use(ScoutVue)\n */\nexport const ScoutVue = {\n install(app) {\n app.config.errorHandler = (err, vm, info) => {\n captureError({\n message: err.message,\n stack: err.stack,\n errorTrace: err.stack,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-error-handler',\n info,\n })\n }\n\n app.config.warnHandler = (msg, vm, trace) => {\n captureError({\n message: msg,\n component: vm?.$options?.name || vm?.$options?.__name || 'Anonymous',\n type: 'vue-warn-handler',\n errorTrace: trace,\n })\n }\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["defaultConfig", "config", "scope", "userInteractions", "pageloadId", "userContext", "customContext", "breadcrumbs", "_consoleLog", "generateId", "prefix", "getIds", "userId", "sessionId", "pageloadId", "getBrowser", "ua", "b", "getOS", "o", "captureBrowserDetails", "conn", "userInteractions", "postData", "url", "data", "controller", "timeout", "headers", "config", "r", "pushErrorEvent", "obj", "details", "config", "captureBrowserDetails", "event", "scope", "getIds", "userContext", "customContext", "breadcrumbs", "_consoleLog", "lines", "filtered", "i", "stack", "match", "postData", "captureError", "ScoutVue", "app", "err", "vm", "info", "captureError", "msg", "trace"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scout-error",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "Lightweight error tracking for JavaScript applications",
5
5
  "author": "James Futhey",
6
6
  "license": "MIT",