@runtimescope/sdk 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -3
- package/dist/index.d.ts +50 -3
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type EventType = 'network' | 'console' | 'session' | 'state' | 'render' | 'dom_snapshot' | 'performance' | 'database' | 'custom' | 'navigation';
|
|
1
|
+
type EventType = 'network' | 'console' | 'session' | 'state' | 'render' | 'dom_snapshot' | 'performance' | 'database' | 'custom' | 'navigation' | 'ui';
|
|
2
2
|
interface BaseEvent {
|
|
3
3
|
eventId: string;
|
|
4
4
|
sessionId: string;
|
|
@@ -48,6 +48,7 @@ interface SessionEvent extends BaseEvent {
|
|
|
48
48
|
connectedAt: number;
|
|
49
49
|
sdkVersion: string;
|
|
50
50
|
buildMeta?: BuildMeta;
|
|
51
|
+
user?: UserContext;
|
|
51
52
|
}
|
|
52
53
|
interface StateEvent extends BaseEvent {
|
|
53
54
|
eventType: 'state';
|
|
@@ -121,7 +122,24 @@ interface CustomEvent extends BaseEvent {
|
|
|
121
122
|
name: string;
|
|
122
123
|
properties?: Record<string, unknown>;
|
|
123
124
|
}
|
|
124
|
-
type
|
|
125
|
+
type UIInteractionAction = 'click' | 'breadcrumb';
|
|
126
|
+
interface UIInteractionEvent extends BaseEvent {
|
|
127
|
+
eventType: 'ui';
|
|
128
|
+
action: UIInteractionAction;
|
|
129
|
+
/** CSS selector or element description */
|
|
130
|
+
target: string;
|
|
131
|
+
/** Visible text (button label, link text) */
|
|
132
|
+
text?: string;
|
|
133
|
+
/** Optional extra context */
|
|
134
|
+
data?: Record<string, unknown>;
|
|
135
|
+
}
|
|
136
|
+
type RuntimeEvent = NetworkEvent | ConsoleEvent | SessionEvent | StateEvent | RenderEvent | DomSnapshotEvent | PerformanceEvent | NavigationEvent | CustomEvent | UIInteractionEvent;
|
|
137
|
+
interface UserContext {
|
|
138
|
+
id?: string;
|
|
139
|
+
email?: string;
|
|
140
|
+
name?: string;
|
|
141
|
+
[key: string]: unknown;
|
|
142
|
+
}
|
|
125
143
|
interface RuntimeScopeConfig {
|
|
126
144
|
enabled?: boolean;
|
|
127
145
|
serverUrl?: string;
|
|
@@ -139,6 +157,7 @@ interface RuntimeScopeConfig {
|
|
|
139
157
|
capturePerformance?: boolean;
|
|
140
158
|
captureRenders?: boolean;
|
|
141
159
|
captureNavigation?: boolean;
|
|
160
|
+
captureClicks?: boolean;
|
|
142
161
|
stores?: Record<string, unknown>;
|
|
143
162
|
beforeSend?: (event: RuntimeEvent) => RuntimeEvent | null;
|
|
144
163
|
redactHeaders?: string[];
|
|
@@ -149,13 +168,29 @@ interface RuntimeScopeConfig {
|
|
|
149
168
|
}[];
|
|
150
169
|
batchSize?: number;
|
|
151
170
|
flushIntervalMs?: number;
|
|
171
|
+
/** Probabilistic sample rate: 0.0–1.0 (default: 1.0 = keep all). Set to 0.1 for production. */
|
|
172
|
+
sampleRate?: number;
|
|
173
|
+
/** Max events per second before dropping (default: unlimited) */
|
|
174
|
+
maxEventsPerSecond?: number;
|
|
175
|
+
/** Initial user context attached to all events */
|
|
176
|
+
user?: UserContext;
|
|
152
177
|
}
|
|
153
178
|
|
|
154
179
|
declare class RuntimeScope {
|
|
155
180
|
private static transport;
|
|
156
181
|
private static restoreFns;
|
|
157
182
|
private static _sessionId;
|
|
183
|
+
private static _state;
|
|
184
|
+
private static _sampleRate;
|
|
185
|
+
private static _maxEventsPerSecond;
|
|
186
|
+
private static _windowCount;
|
|
187
|
+
private static _windowStart;
|
|
188
|
+
private static _user;
|
|
158
189
|
static get sessionId(): string | null;
|
|
190
|
+
/** Returns true if the SDK is currently connected */
|
|
191
|
+
static get isConnected(): boolean;
|
|
192
|
+
/** Probabilistic + rate-limit sampling. Returns true if the event should be sent. */
|
|
193
|
+
private static shouldSample;
|
|
159
194
|
static connect(config?: RuntimeScopeConfig): void;
|
|
160
195
|
private static handleCommand;
|
|
161
196
|
/** Alias for `connect` — used by script-tag snippets */
|
|
@@ -167,7 +202,19 @@ declare class RuntimeScope {
|
|
|
167
202
|
* to build causal chains and detect failures.
|
|
168
203
|
*/
|
|
169
204
|
static track(name: string, properties?: Record<string, unknown>): void;
|
|
205
|
+
/**
|
|
206
|
+
* Set user context attached to the current session.
|
|
207
|
+
* Call this after login to associate events with a specific user.
|
|
208
|
+
* Pass null to clear user context.
|
|
209
|
+
*/
|
|
210
|
+
static setUser(user: UserContext | null): void;
|
|
211
|
+
/**
|
|
212
|
+
* Add a manual breadcrumb to the event trail.
|
|
213
|
+
* Use this to mark meaningful moments that help debug errors
|
|
214
|
+
* (e.g., "user opened settings", "form validated", "retry attempt 2").
|
|
215
|
+
*/
|
|
216
|
+
static addBreadcrumb(message: string, data?: Record<string, unknown>): void;
|
|
170
217
|
static disconnect(): void;
|
|
171
218
|
}
|
|
172
219
|
|
|
173
|
-
export { type BuildMeta, type ConsoleEvent, type CustomEvent, type DomSnapshotEvent, type NavigationEvent, type NetworkEvent, type PerformanceEvent, type RenderEvent, type RuntimeEvent, RuntimeScope, type RuntimeScopeConfig, type SessionEvent, type StateEvent, RuntimeScope as default };
|
|
220
|
+
export { type BuildMeta, type ConsoleEvent, type CustomEvent, type DomSnapshotEvent, type NavigationEvent, type NetworkEvent, type PerformanceEvent, type RenderEvent, type RuntimeEvent, RuntimeScope, type RuntimeScopeConfig, type SessionEvent, type StateEvent, type UIInteractionEvent, type UserContext, RuntimeScope as default };
|
package/dist/index.global.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
"use strict";var RuntimeScope=(()=>{var N=Object.defineProperty;var Z=Object.getOwnPropertyDescriptor;var ee=Object.getOwnPropertyNames;var te=Object.prototype.hasOwnProperty;var ne=(e,t,n)=>t in e?N(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var re=(e,t)=>{for(var n in t)N(e,n,{get:t[n],enumerable:!0})},oe=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ee(t))!te.call(e,r)&&r!==n&&N(e,r,{get:()=>t[r],enumerable:!(o=Z(t,r))||o.enumerable});return e};var se=e=>oe(N({},"__esModule",{value:!0}),e);var m=(e,t,n)=>ne(e,typeof t!="symbol"?t+"":t,n);var _e={};re(_e,{RuntimeScope:()=>_,default:()=>Ie});var F=console.debug.bind(console),k=class k{constructor(t){m(this,"ws",null);m(this,"batch",[]);m(this,"offlineQueue",[]);m(this,"flushTimer",null);m(this,"reconnectTimer",null);m(this,"reconnectDelay",1e3);m(this,"connected",!1);m(this,"stopped",!1);m(this,"config");m(this,"commandHandler",null);m(this,"hasEverConnected",!1);m(this,"connectionWarningTimer",null);this.config=t}connect(){this.stopped=!1,this.doConnect(),this.connectionWarningTimer=setTimeout(()=>{!this.hasEverConnected&&!this.stopped&&console.warn(`[RuntimeScope] SDK has not connected to ${this.config.serverUrl} after 10s. Is the collector running? Start it with: npx @runtimescope/collector`)},k.CONNECTION_WARNING_DELAY)}doConnect(){if(!this.stopped){try{this.ws=new WebSocket(this.config.serverUrl)}catch{this.scheduleReconnect();return}this.ws.onmessage=t=>{try{let n=JSON.parse(String(t.data));n.type==="command"&&n.payload&&this.commandHandler&&this.commandHandler(n.payload),n.type==="error"&&n.payload?.code==="AUTH_FAILED"&&(F("[RuntimeScope] Authentication failed \u2014 stopping reconnection"),this.stopped=!0)}catch{}},this.ws.onopen=()=>{if(this.connected=!0,this.hasEverConnected=!0,this.reconnectDelay=1e3,F(`[RuntimeScope] Connected to ${this.config.serverUrl}`),this.sendRaw({type:"handshake",payload:{appName:this.config.appName,sdkVersion:this.config.sdkVersion,sessionId:this.config.sessionId,...this.config.authToken?{authToken:this.config.authToken}:{}},timestamp:Date.now(),sessionId:this.config.sessionId}),this.offlineQueue.length>0){let t=this.offlineQueue.splice(0);for(let n of t)this.batch.push(n);this.flush()}this.flushTimer=setInterval(()=>this.flush(),this.config.flushIntervalMs)},this.ws.onclose=()=>{this.connected=!1,this.clearFlushTimer(),this.stopped||(F("[RuntimeScope] Disconnected, will reconnect..."),this.scheduleReconnect())},this.ws.onerror=()=>{F(`[RuntimeScope] WebSocket error connecting to ${this.config.serverUrl}`)}}}send(t){this.connected?(this.batch.push(t),this.batch.length>=this.config.batchSize&&this.flush()):this.offlineQueue.length<k.MAX_OFFLINE_QUEUE&&this.offlineQueue.push(t)}flush(){if(this.batch.length===0||!this.connected||!this.ws)return;let t=this.batch.splice(0);this.sendRaw({type:"event",payload:{events:t},timestamp:Date.now(),sessionId:this.config.sessionId})}sendRaw(t){if(this.ws&&this.ws.readyState===WebSocket.OPEN)try{this.ws.send(JSON.stringify(t))}catch{}}scheduleReconnect(){if(this.stopped||this.reconnectTimer)return;let t=this.reconnectDelay*.25*(Math.random()*2-1),n=Math.min(this.reconnectDelay+t,k.MAX_RECONNECT_DELAY);this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.reconnectDelay=Math.min(this.reconnectDelay*2,k.MAX_RECONNECT_DELAY),this.doConnect()},n)}clearFlushTimer(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null)}onCommand(t){this.commandHandler=t}sendCommandResponse(t,n,o){this.sendRaw({type:"command_response",requestId:t,command:n,payload:o,timestamp:Date.now(),sessionId:this.config.sessionId})}disconnect(){this.stopped=!0,this.clearFlushTimer(),this.connectionWarningTimer&&(clearTimeout(this.connectionWarningTimer),this.connectionWarningTimer=null),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.flush(),this.ws&&(this.ws.onclose=null,this.ws.onerror=null,this.ws.close(),this.ws=null),this.connected=!1,this.batch=[],this.offlineQueue=[]}};m(k,"MAX_OFFLINE_QUEUE",1e3),m(k,"MAX_RECONNECT_DELAY",3e4),m(k,"CONNECTION_WARNING_DELAY",1e4);var B=k;function l(){let e=new Uint8Array(4);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function A(){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}var M=new Set;function q(e,t,n,o){let r=window.fetch,c=new Set(n.map(s=>s.toLowerCase())),i=o?.captureBody??!1,a=o?.maxBodySize??65536;return window.fetch=async function(s,u){let d=performance.now(),p=typeof s=="string"?s:s instanceof URL?s.href:s.url,g=(u?.method??"GET").toUpperCase(),R=ie(u?.headers,c),y=ce(u?.body),T=de(u?.body),C;i&&u?.body&&(C=ue(u.body,a));let S=`${g}:${p}:${d}`;M.add(S),setTimeout(()=>M.delete(S),5e3);try{let h=await r.call(window,s,u),L=performance.now()-d,b=parseInt(h.headers.get("content-length")||"0",10),f=ae(h.headers,c),w;if(i)try{let I=await h.clone().text();w=I.length>a?I.slice(0,a):I}catch{}let E={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"network",url:p,method:g,status:h.status,requestHeaders:R,responseHeaders:f,requestBodySize:y,responseBodySize:b,duration:L,ttfb:L,graphqlOperation:T,requestBody:C,responseBody:w,source:"fetch"};if(o?.beforeSend){let O=o.beforeSend(E);O&&e(O)}else e(E);return h}catch(h){let L=performance.now()-d,b="error",f="";h instanceof DOMException&&h.name==="AbortError"?(b="abort",f="Request aborted"):h instanceof Error&&(f=h.message);let w={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"network",url:p,method:g,status:0,requestHeaders:R,responseHeaders:{},requestBodySize:y,responseBodySize:0,duration:L,ttfb:0,graphqlOperation:T,requestBody:C,errorPhase:b,errorMessage:f,source:"fetch"};if(o?.beforeSend){let E=o.beforeSend(w);E&&e(E)}else e(w);throw h}},()=>{window.fetch=r}}function ie(e,t){let n={};if(!e)return n;if(e instanceof Headers)e.forEach((o,r)=>{n[r]=t.has(r.toLowerCase())?"[REDACTED]":o});else if(Array.isArray(e))for(let[o,r]of e)n[o]=t.has(o.toLowerCase())?"[REDACTED]":r;else for(let[o,r]of Object.entries(e))n[o]=t.has(o.toLowerCase())?"[REDACTED]":r;return n}function ae(e,t){let n={};return e.forEach((o,r)=>{n[r]=t.has(r.toLowerCase())?"[REDACTED]":o}),n}function ce(e){return e?typeof e=="string"?new Blob([e]).size:e instanceof Blob?e.size:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:e instanceof FormData?0:e instanceof URLSearchParams?new Blob([e.toString()]).size:0:0}function ue(e,t){if(e){if(typeof e=="string")return e.length>t?e.slice(0,t):e;if(e instanceof URLSearchParams){let n=e.toString();return n.length>t?n.slice(0,t):n}if(e instanceof FormData)return"[FormData]";if(e instanceof Blob)return`[Blob ${e.size} bytes]`;if(e instanceof ArrayBuffer)return`[ArrayBuffer ${e.byteLength} bytes]`;if(ArrayBuffer.isView(e))return`[TypedArray ${e.byteLength} bytes]`}}function de(e){if(!(!e||typeof e!="string"))try{let t=JSON.parse(e);if(typeof t.query=="string"){let n=t.query.trim(),o="query";n.startsWith("mutation")?o="mutation":n.startsWith("subscription")&&(o="subscription");let r=t.operationName||pe(n)||"anonymous";return{type:o,name:r}}}catch{}}function pe(e){return e.match(/^(?:query|mutation|subscription)\s+(\w+)/)?.[1]}function v(e,t=5){let n=new WeakSet;function o(r,c){if(c>t)return"[max depth]";if(r==null)return r;if(typeof r=="function")return`[Function: ${r.name||"anonymous"}]`;if(typeof r=="symbol"||typeof r=="bigint")return r.toString();if(typeof r!="object")return r;if(r instanceof Error)return{name:r.name,message:r.message,stack:r.stack};if(r instanceof Date)return r.toISOString();if(r instanceof RegExp)return r.toString();if(n.has(r))return"[Circular]";if(n.add(r),Array.isArray(r))return r.map(u=>o(u,c+1));let i={},a;try{a=Object.keys(r)}catch{return"[Object]"}let s=50;for(let u=0;u<Math.min(a.length,s);u++)try{i[a[u]]=o(r[a[u]],c+1)}catch{i[a[u]]="[Error accessing property]"}return a.length>s&&(i["..."]=`${a.length-s} more keys`),i}return o(e,0)}var z=["log","warn","error","info","debug","trace"];function j(e,t,n){let o={};for(let r of z)o[r]=console[r].bind(console),console[r]=(...c)=>{let i=c.map(s=>typeof s=="string"?s:fe(s)).join(" "),a={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"console",level:r,message:i,args:c.map(s=>v(s,3)),stackTrace:r==="error"||r==="trace"?new Error().stack?.split(`
|
|
1
|
+
"use strict";var RuntimeScope=(()=>{var M=Object.defineProperty;var ie=Object.getOwnPropertyDescriptor;var ae=Object.getOwnPropertyNames;var ce=Object.prototype.hasOwnProperty;var ue=(e,t,n)=>t in e?M(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var de=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},le=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ae(t))!ce.call(e,s)&&s!==n&&M(e,s,{get:()=>t[s],enumerable:!(r=ie(t,s))||r.enumerable});return e};var pe=e=>le(M({},"__esModule",{value:!0}),e);var p=(e,t,n)=>ue(e,typeof t!="symbol"?t+"":t,n);var Xe={};de(Xe,{RuntimeScope:()=>E,default:()=>je});var k=console.debug.bind(console),R=class R{constructor(t){p(this,"ws",null);p(this,"batch",[]);p(this,"offlineQueue",[]);p(this,"flushTimer",null);p(this,"reconnectTimer",null);p(this,"reconnectDelay",500);p(this,"reconnectAttempt",0);p(this,"connected",!1);p(this,"stopped",!1);p(this,"config");p(this,"commandHandler",null);p(this,"hasEverConnected",!1);p(this,"connectionWarningTimer",null);p(this,"visibilityHandler",null);p(this,"onlineHandler",null);this.config=t}connect(){this.stopped=!1,this.doConnect(),this.connectionWarningTimer=setTimeout(()=>{!this.hasEverConnected&&!this.stopped&&console.warn(`[RuntimeScope] SDK has not connected to ${this.config.serverUrl} after 10s. Is the collector running? Start it with: npx @runtimescope/collector`)},R.CONNECTION_WARNING_DELAY),typeof document<"u"&&(this.visibilityHandler=()=>{document.visibilityState==="visible"&&!this.connected&&!this.stopped&&(k("[RuntimeScope] Tab visible \u2014 attempting immediate reconnect"),this.resetReconnectState(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.doConnect())},document.addEventListener("visibilitychange",this.visibilityHandler)),typeof window<"u"&&(this.onlineHandler=()=>{!this.connected&&!this.stopped&&(k("[RuntimeScope] Network online \u2014 attempting immediate reconnect"),this.resetReconnectState(),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.doConnect())},window.addEventListener("online",this.onlineHandler))}doConnect(){if(!this.stopped){try{this.ws=new WebSocket(this.config.serverUrl)}catch{this.scheduleReconnect();return}this.ws.onmessage=t=>{try{let n=JSON.parse(String(t.data));n.type==="command"&&n.payload&&this.commandHandler&&this.commandHandler(n.payload),n.type==="__server_restart"&&(k("[RuntimeScope] Server restart notice received \u2014 will reconnect immediately"),this.resetReconnectState()),n.type==="error"&&n.payload?.code==="AUTH_FAILED"&&(k("[RuntimeScope] Authentication failed \u2014 stopping reconnection"),this.stopped=!0)}catch{}},this.ws.onopen=()=>{if(this.connected=!0,this.hasEverConnected=!0,this.resetReconnectState(),k(`[RuntimeScope] Connected to ${this.config.serverUrl}`),this.sendRaw({type:"handshake",payload:{appName:this.config.appName,sdkVersion:this.config.sdkVersion,sessionId:this.config.sessionId,...this.config.authToken?{authToken:this.config.authToken}:{}},timestamp:Date.now(),sessionId:this.config.sessionId}),this.offlineQueue.length>0){let t=this.offlineQueue.splice(0);for(let n of t)this.batch.push(n);this.flush()}this.flushTimer=setInterval(()=>this.flush(),this.config.flushIntervalMs)},this.ws.onclose=()=>{this.connected=!1,this.clearFlushTimer(),this.stopped||(k("[RuntimeScope] Disconnected, will reconnect..."),this.scheduleReconnect())},this.ws.onerror=()=>{k(`[RuntimeScope] WebSocket error connecting to ${this.config.serverUrl}`)}}}send(t){this.connected?(this.batch.push(t),this.batch.length>=this.config.batchSize&&this.flush()):this.offlineQueue.length<R.MAX_OFFLINE_QUEUE&&this.offlineQueue.push(t)}flush(){if(this.batch.length===0||!this.connected||!this.ws)return;let t=this.batch.splice(0);this.sendRaw({type:"event",payload:{events:t},timestamp:Date.now(),sessionId:this.config.sessionId})}sendRaw(t){if(this.ws&&this.ws.readyState===WebSocket.OPEN)try{this.ws.send(JSON.stringify(t))}catch{}}scheduleReconnect(){if(this.stopped||this.reconnectTimer)return;this.reconnectAttempt++;let t;if(this.reconnectAttempt<=R.FAST_RETRY_COUNT)t=R.FAST_RETRY_DELAY;else{let n=this.reconnectDelay*.25*(Math.random()*2-1);t=Math.min(this.reconnectDelay+n,R.MAX_RECONNECT_DELAY),this.reconnectDelay=Math.min(this.reconnectDelay*2,R.MAX_RECONNECT_DELAY)}this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.doConnect()},t)}resetReconnectState(){this.reconnectDelay=500,this.reconnectAttempt=0}clearFlushTimer(){this.flushTimer&&(clearInterval(this.flushTimer),this.flushTimer=null)}onCommand(t){this.commandHandler=t}sendCommandResponse(t,n,r){this.sendRaw({type:"command_response",requestId:t,command:n,payload:r,timestamp:Date.now(),sessionId:this.config.sessionId})}disconnect(){this.stopped=!0,this.clearFlushTimer(),this.connectionWarningTimer&&(clearTimeout(this.connectionWarningTimer),this.connectionWarningTimer=null),this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.visibilityHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.onlineHandler&&typeof window<"u"&&(window.removeEventListener("online",this.onlineHandler),this.onlineHandler=null),this.flush(),this.ws&&(this.ws.onclose=null,this.ws.onerror=null,this.ws.close(),this.ws=null),this.connected=!1,this.batch=[],this.offlineQueue=[]}};p(R,"MAX_OFFLINE_QUEUE",1e3),p(R,"MAX_RECONNECT_DELAY",3e4),p(R,"CONNECTION_WARNING_DELAY",1e4),p(R,"FAST_RETRY_COUNT",3),p(R,"FAST_RETRY_DELAY",500);var F=R;function m(){let e=new Uint8Array(8);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}function $(){let e=new Uint8Array(16);return crypto.getRandomValues(e),Array.from(e,t=>t.toString(16).padStart(2,"0")).join("")}var fe=1e3,me=1e4,he=5e3,C=new Map,x=null,P=0;function ve(){P++,!x&&(x=setInterval(()=>{let e=Date.now()-me;for(let[t,n]of C)n<e&&C.delete(t)},he))}function ge(){P--,P<=0&&x&&(clearInterval(x),x=null,P=0)}function W(e,t,n,r){let s=window.fetch,c=new Set(n.map(a=>a.toLowerCase())),o=r?.captureBody??!1,i=r?.maxBodySize??65536;return ve(),window.fetch=async function(a,u){let d=performance.now(),l=typeof a=="string"?a:a instanceof URL?a.href:a.url,f=(u?.method??"GET").toUpperCase(),b=ye(u?.headers,c),g=Re(u?.body),T=Se(u?.body),D;o&&u?.body&&(D=Ee(u.body,i));let U=`${f}:${l}:${d}`;if(C.size>=fe){let h=C.keys().next().value;h!==void 0&&C.delete(h)}C.set(U,Date.now());try{let h=await s.call(window,a,u),_=performance.now()-d,L=parseInt(h.headers.get("content-length")||"0",10),I=we(h.headers,c),v;if(o)try{let O=await h.clone().text();v=O.length>i?O.slice(0,i):O}catch{}let w={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"network",url:l,method:f,status:h.status,requestHeaders:b,responseHeaders:I,requestBodySize:g,responseBodySize:L,duration:_,ttfb:_,graphqlOperation:T,requestBody:D,responseBody:v,source:"fetch"};if(r?.beforeSend){let S=r.beforeSend(w);S&&e(S)}else e(w);return h}catch(h){let _=performance.now()-d,L="error",I="";h instanceof DOMException&&h.name==="AbortError"?(L="abort",I="Request aborted"):h instanceof Error&&(I=h.message);let v={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"network",url:l,method:f,status:0,requestHeaders:b,responseHeaders:{},requestBodySize:g,responseBodySize:0,duration:_,ttfb:0,graphqlOperation:T,requestBody:D,errorPhase:L,errorMessage:I,source:"fetch"};if(r?.beforeSend){let w=r.beforeSend(v);w&&e(w)}else e(v);throw h}},()=>{window.fetch=s,ge()}}function ye(e,t){let n={};if(!e)return n;if(e instanceof Headers)e.forEach((r,s)=>{n[s]=t.has(s.toLowerCase())?"[REDACTED]":r});else if(Array.isArray(e))for(let[r,s]of e)n[r]=t.has(r.toLowerCase())?"[REDACTED]":s;else for(let[r,s]of Object.entries(e))n[r]=t.has(r.toLowerCase())?"[REDACTED]":s;return n}function we(e,t){let n={};return e.forEach((r,s)=>{n[s]=t.has(s.toLowerCase())?"[REDACTED]":r}),n}function Re(e){return e?typeof e=="string"?new Blob([e]).size:e instanceof Blob?e.size:e instanceof ArrayBuffer||ArrayBuffer.isView(e)?e.byteLength:e instanceof FormData?0:e instanceof URLSearchParams?new Blob([e.toString()]).size:0:0}function Ee(e,t){if(e){if(typeof e=="string")return e.length>t?e.slice(0,t):e;if(e instanceof URLSearchParams){let n=e.toString();return n.length>t?n.slice(0,t):n}if(e instanceof FormData)return"[FormData]";if(e instanceof Blob)return`[Blob ${e.size} bytes]`;if(e instanceof ArrayBuffer)return`[ArrayBuffer ${e.byteLength} bytes]`;if(ArrayBuffer.isView(e))return`[TypedArray ${e.byteLength} bytes]`}}function Se(e){if(!(!e||typeof e!="string"))try{let t=JSON.parse(e);if(typeof t.query=="string"){let n=t.query.trim(),r="query";n.startsWith("mutation")?r="mutation":n.startsWith("subscription")&&(r="subscription");let s=t.operationName||be(n)||"anonymous";return{type:r,name:s}}}catch{}}function be(e){return e.match(/^(?:query|mutation|subscription)\s+(\w+)/)?.[1]}function y(e,t=5){let n=new WeakSet;function r(s,c){if(c>t)return"[max depth]";if(s==null)return s;if(typeof s=="function")return`[Function: ${s.name||"anonymous"}]`;if(typeof s=="symbol"||typeof s=="bigint")return s.toString();if(typeof s!="object")return s;if(s instanceof Error)return{name:s.name,message:s.message,stack:s.stack};if(s instanceof Date)return s.toISOString();if(s instanceof RegExp)return s.toString();if(n.has(s))return"[Circular]";if(n.add(s),Array.isArray(s))return s.map(u=>r(u,c+1));let o={},i;try{i=Object.keys(s)}catch{return"[Object]"}let a=50;for(let u=0;u<Math.min(i.length,a);u++)try{o[i[u]]=r(s[i[u]],c+1)}catch{o[i[u]]="[Error accessing property]"}return i.length>a&&(o["..."]=`${i.length-a} more keys`),o}return r(e,0)}var V=["log","warn","error","info","debug","trace"];function G(e,t,n){let r={};for(let s of V)r[s]=console[s].bind(console),console[s]=(...c)=>{let o=c.map(a=>typeof a=="string"?a:_e(a)).join(" "),i={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"console",level:s,message:o,args:c.map(a=>y(a,3)),stackTrace:s==="error"||s==="trace"?new Error().stack?.split(`
|
|
2
2
|
`).slice(2).join(`
|
|
3
|
-
`):void 0,sourceFile:void 0};if(n){let s=n(a);s&&e(s)}else e(a);o[r](...c)};return()=>{for(let r of z)console[r]=o[r]}}function fe(e){try{return JSON.stringify(e)}catch{return String(e)}}function U(e,t,n,o){let r=new Set(n.map(d=>d.toLowerCase())),c=o?.captureBody??!1,i=o?.maxBodySize??65536,a=XMLHttpRequest.prototype.open,s=XMLHttpRequest.prototype.setRequestHeader,u=XMLHttpRequest.prototype.send;return XMLHttpRequest.prototype.open=function(d,p){return this.__rs_method=d.toUpperCase(),this.__rs_url=typeof p=="string"?p:p.href,this.__rs_headers={},a.apply(this,arguments)},XMLHttpRequest.prototype.setRequestHeader=function(d,p){return this.__rs_headers&&(this.__rs_headers[d.toLowerCase()]=r.has(d.toLowerCase())?"[REDACTED]":p),s.call(this,d,p)},XMLHttpRequest.prototype.send=function(d){let p=this.__rs_method??"GET",g=this.__rs_url??"",R=`${p}:${g}`;if(Array.from(M).some(f=>f.startsWith(R)))return this.__rs_fetchIntercepted=!0,u.call(this,d);let T={...this.__rs_headers??{}},C=performance.now(),S,h=0;if(d){if(typeof d=="string")h=new Blob([d]).size,c&&(S=d.length>i?d.slice(0,i):d);else if(d instanceof Blob)h=d.size,c&&(S=`[Blob ${d.size} bytes]`);else if(d instanceof ArrayBuffer)h=d.byteLength,c&&(S=`[ArrayBuffer ${d.byteLength} bytes]`);else if(d instanceof FormData)c&&(S="[FormData]");else if(d instanceof URLSearchParams){let f=d.toString();h=new Blob([f]).size,c&&(S=f.length>i?f.slice(0,i):f)}}let L=me(d),b=f=>{let w={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"network",url:g,method:p,status:0,requestHeaders:T,responseHeaders:{},requestBodySize:h,responseBodySize:0,duration:0,ttfb:0,graphqlOperation:L,requestBody:S,source:"xhr",...f};if(o?.beforeSend){let E=o.beforeSend(w);E&&e(E)}else e(w)};return this.addEventListener("load",()=>{let f=performance.now()-C,w=le(this.getAllResponseHeaders(),r),E=parseInt(this.getResponseHeader("content-length")||"0",10),O;if(c&&this.responseType===""||this.responseType==="text")try{let I=this.responseText;O=I.length>i?I.slice(0,i):I}catch{}b({status:this.status,responseHeaders:w,responseBodySize:E,responseBody:O,duration:f,ttfb:f})}),this.addEventListener("error",()=>{let f=performance.now()-C;b({duration:f,errorPhase:"error",errorMessage:"Network error"})}),this.addEventListener("abort",()=>{let f=performance.now()-C;b({duration:f,errorPhase:"abort",errorMessage:"Request aborted"})}),this.addEventListener("timeout",()=>{let f=performance.now()-C;b({duration:f,errorPhase:"timeout",errorMessage:`Request timed out after ${this.timeout}ms`})}),u.call(this,d)},()=>{XMLHttpRequest.prototype.open=a,XMLHttpRequest.prototype.setRequestHeader=s,XMLHttpRequest.prototype.send=u}}function le(e,t){let n={};if(!e)return n;for(let o of e.trim().split(/[\r\n]+/)){let r=o.indexOf(":");if(r===-1)continue;let c=o.slice(0,r).trim().toLowerCase(),i=o.slice(r+1).trim();n[c]=t.has(c)?"[REDACTED]":i}return n}function me(e){if(!(!e||typeof e!="string"))try{let t=JSON.parse(e);if(typeof t.query=="string"){let n=t.query.trim(),o="query";n.startsWith("mutation")?o="mutation":n.startsWith("subscription")&&(o="subscription");let r=t.operationName||he(n)||"anonymous";return{type:o,name:r}}}catch{}}function he(e){return e.match(/^(?:query|mutation|subscription)\s+(\w+)/)?.[1]}function $(e,t,n,o){let r=[],c=new Map;for(let[i,a]of Object.entries(n)){let s=ge(a);if(s==="zustand"){let u=a;x(e,t,o?.beforeSend,{storeId:i,library:s,phase:"init",state:v(u.getState(),4)});let d=u.subscribe((p,g)=>{let R=X(g,p);x(e,t,o?.beforeSend,{storeId:i,library:s,phase:"update",state:v(p,4),previousState:v(g,4),diff:R?v(R,3):void 0})});r.push(d)}else if(s==="redux"){let u=a;x(e,t,o?.beforeSend,{storeId:i,library:s,phase:"init",state:v(u.getState(),4)});let d,p=u.dispatch.bind(u);c.set(i,p),u.dispatch=y=>(y&&typeof y=="object"&&"type"in y&&(d={type:String(y.type),payload:y.payload}),p(y));let g=u.getState(),R=u.subscribe(()=>{let y=u.getState(),T=X(g,y);x(e,t,o?.beforeSend,{storeId:i,library:s,phase:"update",state:v(y,4),previousState:v(g,4),diff:T?v(T,3):void 0,action:d?v(d,3):void 0}),g=y,d=void 0});r.push(R)}}return()=>{for(let i of r)i();for(let[i,a]of c){let s=n[i];s&&(s.dispatch=a)}}}function ge(e){if(!e||typeof e!="object")return"unknown";let t=e;return typeof t.getState=="function"&&typeof t.setState=="function"&&typeof t.subscribe=="function"?"zustand":typeof t.dispatch=="function"&&typeof t.getState=="function"&&typeof t.subscribe=="function"?"redux":"unknown"}function X(e,t){if(!e||!t||typeof e!="object"||typeof t!="object")return null;let n={},o=e,r=t,c=new Set([...Object.keys(o),...Object.keys(r)]);for(let i of c)o[i]!==r[i]&&(n[i]={from:o[i],to:r[i]});return Object.keys(n).length>0?n:null}function x(e,t,n,o){let r={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"state",...o};if(n){let c=n(r);c&&e(c)}else e(r)}var ve={LCP:[2500,4e3],FCP:[1800,3e3],CLS:[.1,.25],TTFB:[800,1800],FID:[100,300],INP:[200,500]};function ye(e,t){let[n,o]=ve[e]??[1/0,1/0];return t<=n?"good":t<=o?"needs-improvement":"poor"}function W(e,t,n){let o=[],r=(a,s,u)=>{let d={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"performance",metricName:a,value:Math.round(s*100)/100,rating:ye(a,s),element:u};if(n?.beforeSend){let p=n.beforeSend(d);p&&e(p)}else e(d)};D(o,"largest-contentful-paint",a=>{let s=a[a.length-1];if(!s)return;let u=s.element;r("LCP",s.startTime,u?.tagName?.toLowerCase())}),D(o,"paint",a=>{for(let s of a)s.name==="first-contentful-paint"&&r("FCP",s.startTime)});let c=0;D(o,"layout-shift",a=>{for(let s of a){let u=s;!u.hadRecentInput&&u.value&&(c+=u.value,r("CLS",c))}}),D(o,"first-input",a=>{let s=a[0];if(!s)return;let u=s;u.processingStart&&r("FID",u.processingStart-s.startTime)}),D(o,"navigation",a=>{let s=a[0];s&&r("TTFB",s.responseStart-s.requestStart)});let i=0;return D(o,"event",a=>{for(let s of a)s.duration>i&&(i=s.duration,r("INP",i))},{durationThreshold:16}),()=>{for(let a of o)try{a.disconnect()}catch{}}}function D(e,t,n,o){try{let r=new PerformanceObserver(c=>{n(c.getEntries())});r.observe({type:t,buffered:!0,...o}),e.push(r)}catch{}}var we=0,Ee=1,G=1e4,V=100;function Q(e,t,n){let o=new Map,r=n?.snapshotIntervalMs??5e3,c=null,i=Re();if(!i)return()=>{};let a=i.onCommitFiberRoot;return i._runtimescope_original=a,i.onCommitFiberRoot=(s,u)=>{if(a)try{a(s,u)}catch{}u.current&&H(u.current,o)},c=setInterval(()=>{Te(o,e,t,n?.beforeSend)},r),()=>{c&&(clearInterval(c),c=null),i&&(i._runtimescope_original?i.onCommitFiberRoot=i._runtimescope_original:delete i.onCommitFiberRoot,delete i._runtimescope_original)}}function Re(){if(typeof window>"u")return null;let e=window;return e.__REACT_DEVTOOLS_GLOBAL_HOOK__||(e.__REACT_DEVTOOLS_GLOBAL_HOOK__={}),e.__REACT_DEVTOOLS_GLOBAL_HOOK__}function H(e,t){Se(e,t),e.child&&H(e.child,t),e.sibling&&H(e.sibling,t)}function Se(e,t){if(e.tag!==we&&e.tag!==Ee)return;let n=be(e);if(!n)return;let o=Date.now(),r=e.alternate===null,c=e.actualDuration??0,i=ke(e,r),a=t.get(n);a||(a={renderCount:0,totalDuration:0,lastRenderTime:0,lastRenderPhase:"mount",lastRenderCause:"unknown",renderTimestamps:[]},t.set(n,a)),a.renderCount++,a.totalDuration+=c,a.lastRenderTime=o,a.lastRenderPhase=r?"mount":"update",a.lastRenderCause=i??"unknown",a.renderTimestamps.push(o),a.renderTimestamps.length>V&&(a.renderTimestamps=a.renderTimestamps.slice(-V))}function be(e){if(e.type&&typeof e.type!="string")return e.type.displayName||e.type.name||void 0}function ke(e,t){return t?"props":e.alternate?e.memoizedProps!==e.alternate.memoizedProps?"props":e.memoizedState!==e.alternate.memoizedState?"state":"parent":"unknown"}function Ce(e){if(e.length<2)return 0;let t=Date.now(),n=t-G,o=e.filter(c=>c>=n);if(o.length<2)return 0;let r=t-o[0];return r===0?0:o.length/(r/1e3)}function Te(e,t,n,o){if(e.size===0)return;let r=[],c=[],i=0;for(let[s,u]of e){let d=Ce(u.renderTimestamps),p=d>4||u.renderCount>20;r.push({componentName:s,renderCount:u.renderCount,totalDuration:Math.round(u.totalDuration*100)/100,avgDuration:u.renderCount>0?Math.round(u.totalDuration/u.renderCount*100)/100:0,lastRenderPhase:u.lastRenderPhase,lastRenderCause:u.lastRenderCause,renderVelocity:Math.round(d*100)/100,suspicious:p}),p&&c.push(s),i+=u.renderCount}r.sort((s,u)=>u.renderCount-s.renderCount);let a={eventId:l(),sessionId:n,timestamp:Date.now(),eventType:"render",profiles:r,snapshotWindowMs:G,totalRenders:i,suspiciousComponents:c};if(o){let s=o(a);s&&t(s)}else t(a);for(let s of e.values())s.renderCount=0,s.totalDuration=0}function K(e,t,n){let o=c=>{let i,a,s;if(c instanceof ErrorEvent)i=c.message||"Uncaught error",a=c.error?.stack,s=c.filename?`${c.filename}:${c.lineno}:${c.colno}`:void 0;else{let d=c.target;if(d&&d!==window){let p=d.tagName?.toLowerCase()??"unknown",g=d.src??d.src??d.href??"unknown";i=`Failed to load resource: <${p}> ${g}`}else return}let u={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"console",level:"error",message:`[Uncaught] ${i}`,args:[v(i,3)],stackTrace:a,sourceFile:s};if(n){let d=n(u);d&&e(d)}else e(u)},r=c=>{let i=c.reason,a,s;if(i instanceof Error)a=i.message,s=i.stack;else if(typeof i=="string")a=i;else try{a=JSON.stringify(i)}catch{a=String(i)}let u={eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"console",level:"error",message:`[Unhandled Rejection] ${a}`,args:[v(i,3)],stackTrace:s,sourceFile:void 0};if(n){let d=n(u);d&&e(d)}else e(u)};return window.addEventListener("error",o,!0),window.addEventListener("unhandledrejection",r),()=>{window.removeEventListener("error",o,!0),window.removeEventListener("unhandledrejection",r)}}function J(e,t){let n=window.location.href;function o(s,u){let d=n;d!==s&&(n=s,e({eventId:l(),sessionId:t,timestamp:Date.now(),eventType:"navigation",from:d,to:s,trigger:u}))}let r=history.pushState.bind(history),c=history.replaceState.bind(history);history.pushState=function(...s){r(...s),o(window.location.href,"pushState")},history.replaceState=function(...s){c(...s),o(window.location.href,"replaceState")};let i=()=>o(window.location.href,"popstate");window.addEventListener("popstate",i);let a=()=>o(window.location.href,"hashchange");return window.addEventListener("hashchange",a),()=>{history.pushState=r,history.replaceState=c,window.removeEventListener("popstate",i),window.removeEventListener("hashchange",a)}}var P="0.7.1",Y=console.debug.bind(console),_=class{static get sessionId(){return this._sessionId}static connect(t={}){if(t.enabled===!1)return;this.transport&&this.disconnect();let n={serverUrl:t.serverUrl??t.endpoint??"ws://localhost:9090",appName:t.appName??"unknown",captureNetwork:t.captureNetwork??!0,captureConsole:t.captureConsole??!0,captureXhr:t.captureXhr??!0,captureBody:t.captureBody??!1,maxBodySize:t.maxBodySize??65536,capturePerformance:t.capturePerformance??!0,captureRenders:t.captureRenders??!0,captureNavigation:t.captureNavigation??!0,stores:t.stores??{},beforeSend:t.beforeSend,redactHeaders:t.redactHeaders??["authorization","cookie"],batchSize:t.batchSize??50,flushIntervalMs:t.flushIntervalMs??100};this._sessionId=A(),this.transport=new B({serverUrl:n.serverUrl,appName:n.appName,sessionId:this._sessionId,sdkVersion:P,authToken:t.authToken,batchSize:n.batchSize,flushIntervalMs:n.flushIntervalMs}),this.transport.connect(),Y(`[RuntimeScope] SDK v${P} initializing \u2014 app: ${n.appName}, server: ${n.serverUrl}`);let o=i=>this.transport?.send(i);o({eventId:l(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"session",appName:n.appName,connectedAt:Date.now(),sdkVersion:P,buildMeta:t.buildMeta});let r=this._sessionId;this.transport.onCommand(i=>{this.handleCommand(i,o,r)}),n.captureNetwork&&this.restoreFns.push(q(o,this._sessionId,n.redactHeaders,{captureBody:n.captureBody,maxBodySize:n.maxBodySize,beforeSend:n.beforeSend})),n.captureXhr&&this.restoreFns.push(U(o,this._sessionId,n.redactHeaders,{captureBody:n.captureBody,maxBodySize:n.maxBodySize,beforeSend:n.beforeSend})),n.captureConsole&&(this.restoreFns.push(j(o,this._sessionId,n.beforeSend)),this.restoreFns.push(K(o,this._sessionId,n.beforeSend))),Object.keys(n.stores).length>0&&this.restoreFns.push($(o,this._sessionId,n.stores,{beforeSend:n.beforeSend})),n.capturePerformance&&this.restoreFns.push(W(o,this._sessionId,{beforeSend:n.beforeSend})),n.captureRenders&&this.restoreFns.push(Q(o,this._sessionId,{beforeSend:n.beforeSend})),n.captureNavigation&&this.restoreFns.push(J(o,this._sessionId));let c=[n.captureNetwork&&"fetch",n.captureXhr&&"xhr",n.captureConsole&&"console, errors",Object.keys(n.stores).length>0&&"state",n.capturePerformance&&"performance",n.captureRenders&&"renders",n.captureNavigation&&"navigation"].filter(Boolean);Y(`[RuntimeScope] Interceptors active \u2014 ${c.join(", ")}`)}static handleCommand(t,n,o){if(t.command==="capture_dom_snapshot"){let r=t.params?.maxSize??5e5,c=document.documentElement.outerHTML,i=c.length>r;i&&(c=c.slice(0,r));let a={eventId:l(),sessionId:o,timestamp:Date.now(),eventType:"dom_snapshot",html:c,url:window.location.href,viewport:{width:window.innerWidth,height:window.innerHeight},scrollPosition:{x:window.scrollX,y:window.scrollY},elementCount:document.querySelectorAll("*").length,truncated:i};n(a),this.transport?.sendCommandResponse(t.requestId,t.command,a)}else this.transport?.sendCommandResponse(t.requestId,t.command,{error:"Unknown command"})}static init(t={}){return this.connect(t)}static track(t,n){if(!this.transport||!this._sessionId)return;let o={eventId:l(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"custom",name:t,properties:n};this.transport.send(o)}static disconnect(){for(let t of this.restoreFns)t();this.restoreFns=[],this.transport?.disconnect(),this.transport=null,this._sessionId=null}};m(_,"transport",null),m(_,"restoreFns",[]),m(_,"_sessionId",null);var Ie=_;return se(_e);})();
|
|
3
|
+
`):void 0,sourceFile:void 0};if(n){let a=n(i);a&&e(a)}else e(i);r[s](...c)};return()=>{for(let s of V)console[s]=r[s]}}function _e(e){try{return JSON.stringify(e)}catch{return String(e)}}function Q(e,t,n,r){let s=new Set(n.map(l=>l.toLowerCase())),c=r?.captureBody??!1,o=r?.maxBodySize??65536,i=new AbortController,a=XMLHttpRequest.prototype.open,u=XMLHttpRequest.prototype.setRequestHeader,d=XMLHttpRequest.prototype.send;return XMLHttpRequest.prototype.open=function(l,f){return this.__rs_method=l.toUpperCase(),this.__rs_url=typeof f=="string"?f:f.href,this.__rs_headers={},a.apply(this,arguments)},XMLHttpRequest.prototype.setRequestHeader=function(l,f){return this.__rs_headers&&(this.__rs_headers[l.toLowerCase()]=s.has(l.toLowerCase())?"[REDACTED]":f),u.call(this,l,f)},XMLHttpRequest.prototype.send=function(l){let f=this.__rs_method??"GET",b=this.__rs_url??"",g=`${f}:${b}`,T=!1;for(let v of C.keys())if(v.startsWith(g)){T=!0;break}if(T)return this.__rs_fetchIntercepted=!0,d.call(this,l);let D={...this.__rs_headers??{}},U=performance.now(),h,_=0;if(l){if(typeof l=="string")_=new Blob([l]).size,c&&(h=l.length>o?l.slice(0,o):l);else if(l instanceof Blob)_=l.size,c&&(h=`[Blob ${l.size} bytes]`);else if(l instanceof ArrayBuffer)_=l.byteLength,c&&(h=`[ArrayBuffer ${l.byteLength} bytes]`);else if(l instanceof FormData)c&&(h="[FormData]");else if(l instanceof URLSearchParams){let v=l.toString();_=new Blob([v]).size,c&&(h=v.length>o?v.slice(0,o):v)}}let L=Ie(l),I=v=>{let w={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"network",url:b,method:f,status:0,requestHeaders:D,responseHeaders:{},requestBodySize:_,responseBodySize:0,duration:0,ttfb:0,graphqlOperation:L,requestBody:h,source:"xhr",...v};if(r?.beforeSend){let S=r.beforeSend(w);S&&e(S)}else e(w)};return this.addEventListener("loadend",()=>{let v=performance.now()-U;if(this.status>0){let w=Te(this.getAllResponseHeaders(),s),S=parseInt(this.getResponseHeader("content-length")||"0",10),O;if(c&&(this.responseType===""||this.responseType==="text"))try{let j=this.responseText;O=j.length>o?j.slice(0,o):j}catch{}I({status:this.status,responseHeaders:w,responseBodySize:S,responseBody:O,duration:v,ttfb:v})}else{let w="error",S="Network error";this.readyState===0||this.status,this.timeout>0&&v>=this.timeout&&(w="timeout",S=`Request timed out after ${this.timeout}ms`),I({duration:v,errorPhase:w,errorMessage:S})}},{once:!0,signal:i.signal}),d.call(this,l)},()=>{i.abort(),XMLHttpRequest.prototype.open=a,XMLHttpRequest.prototype.setRequestHeader=u,XMLHttpRequest.prototype.send=d}}function Te(e,t){let n={};if(!e)return n;for(let r of e.trim().split(/[\r\n]+/)){let s=r.indexOf(":");if(s===-1)continue;let c=r.slice(0,s).trim().toLowerCase(),o=r.slice(s+1).trim();n[c]=t.has(c)?"[REDACTED]":o}return n}function Ie(e){if(!(!e||typeof e!="string"))try{let t=JSON.parse(e);if(typeof t.query=="string"){let n=t.query.trim(),r="query";n.startsWith("mutation")?r="mutation":n.startsWith("subscription")&&(r="subscription");let s=t.operationName||Ce(n)||"anonymous";return{type:r,name:s}}}catch{}}function Ce(e){return e.match(/^(?:query|mutation|subscription)\s+(\w+)/)?.[1]}function Y(e,t,n,r){let s=[],c=new Map;for(let[o,i]of Object.entries(n)){let a=ke(i);if(a==="zustand"){let u=i;B(e,t,r?.beforeSend,{storeId:o,library:a,phase:"init",state:y(u.getState(),4)});let d=u.subscribe((l,f)=>{let b=K(f,l);B(e,t,r?.beforeSend,{storeId:o,library:a,phase:"update",state:y(l,4),previousState:y(f,4),diff:b?y(b,3):void 0})});s.push(d)}else if(a==="redux"){let u=i;B(e,t,r?.beforeSend,{storeId:o,library:a,phase:"init",state:y(u.getState(),4)});let d,l=u.dispatch.bind(u);c.set(o,l),u.dispatch=g=>(g&&typeof g=="object"&&"type"in g&&(d={type:String(g.type),payload:g.payload}),l(g));let f=u.getState(),b=u.subscribe(()=>{let g=u.getState(),T=K(f,g);B(e,t,r?.beforeSend,{storeId:o,library:a,phase:"update",state:y(g,4),previousState:y(f,4),diff:T?y(T,3):void 0,action:d?y(d,3):void 0}),f=g,d=void 0});s.push(b)}}return()=>{for(let o of s)o();for(let[o,i]of c){let a=n[o];a&&(a.dispatch=i)}}}function ke(e){if(!e||typeof e!="object")return"unknown";let t=e;return typeof t.getState=="function"&&typeof t.setState=="function"&&typeof t.subscribe=="function"?"zustand":typeof t.dispatch=="function"&&typeof t.getState=="function"&&typeof t.subscribe=="function"?"redux":"unknown"}function K(e,t){if(!e||!t||typeof e!="object"||typeof t!="object")return null;let n={},r=e,s=t,c=new Set([...Object.keys(r),...Object.keys(s)]);for(let o of c)r[o]!==s[o]&&(n[o]={from:r[o],to:s[o]});return Object.keys(n).length>0?n:null}function B(e,t,n,r){let s={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"state",...r};if(n){let c=n(s);c&&e(c)}else e(s)}var Le={LCP:[2500,4e3],FCP:[1800,3e3],CLS:[.1,.25],TTFB:[800,1800],FID:[100,300],INP:[200,500]};function Oe(e,t){let[n,r]=Le[e]??[1/0,1/0];return t<=n?"good":t<=r?"needs-improvement":"poor"}var H=null;function J(e,t,n){if(H)for(let i of H)try{i.disconnect()}catch{}let r=[];H=r;let s=(i,a,u)=>{let d={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"performance",metricName:i,value:Math.round(a*100)/100,rating:Oe(i,a),element:u};if(n?.beforeSend){let l=n.beforeSend(d);l&&e(l)}else e(d)};N(r,"largest-contentful-paint",i=>{let a=i[i.length-1];if(!a)return;let u=a.element;s("LCP",a.startTime,u?.tagName?.toLowerCase())}),N(r,"paint",i=>{for(let a of i)a.name==="first-contentful-paint"&&s("FCP",a.startTime)});let c=0;N(r,"layout-shift",i=>{for(let a of i){let u=a;!u.hadRecentInput&&u.value&&(c+=u.value,s("CLS",c))}}),N(r,"first-input",i=>{let a=i[0];if(!a)return;let u=a;u.processingStart&&s("FID",u.processingStart-a.startTime)}),N(r,"navigation",i=>{let a=i[0];a&&s("TTFB",a.responseStart-a.requestStart)});let o=0;return N(r,"event",i=>{for(let a of i)a.duration>o&&(o=a.duration,s("INP",o))},{durationThreshold:16}),()=>{for(let i of r)try{i.disconnect()}catch{}H===r&&(H=null)}}function N(e,t,n,r){try{let s=new PerformanceObserver(c=>{n(c.getEntries())});s.observe({type:t,buffered:!0,...r}),e.push(s)}catch{}}var Ne=0,De=1,te=1e4,Z=100,xe=6e4,ee=500;function ne(e,t,n){let r=new Map,s=n?.snapshotIntervalMs??5e3,c=null,o=He();if(!o)return()=>{};let i=o.onCommitFiberRoot;return o._runtimescope_original=i,o.onCommitFiberRoot=(a,u)=>{if(i)try{i(a,u)}catch{}u.current&&X(u.current,r)},c=setInterval(()=>{Be(r,e,t,n?.beforeSend)},s),()=>{c&&(clearInterval(c),c=null),o&&(o._runtimescope_original?o.onCommitFiberRoot=o._runtimescope_original:delete o.onCommitFiberRoot,delete o._runtimescope_original)}}function He(){if(typeof window>"u")return null;let e=window;return e.__REACT_DEVTOOLS_GLOBAL_HOOK__||(e.__REACT_DEVTOOLS_GLOBAL_HOOK__={}),e.__REACT_DEVTOOLS_GLOBAL_HOOK__}function X(e,t){Ae(e,t),e.child&&X(e.child,t),e.sibling&&X(e.sibling,t)}function Ae(e,t){if(e.tag!==Ne&&e.tag!==De)return;let n=Me(e);if(!n)return;let r=Date.now(),s=e.alternate===null,c=e.actualDuration??0,o=Fe(e,s),i=t.get(n);i||(i={renderCount:0,totalDuration:0,lastRenderTime:0,lastRenderPhase:"mount",lastRenderCause:"unknown",renderTimestamps:[]},t.set(n,i)),i.renderCount++,i.totalDuration+=c,i.lastRenderTime=r,i.lastRenderPhase=s?"mount":"update",i.lastRenderCause=o??"unknown",i.renderTimestamps.push(r),i.renderTimestamps.length>Z&&(i.renderTimestamps=i.renderTimestamps.slice(-Z))}function Me(e){if(e.type&&typeof e.type!="string")return e.type.displayName||e.type.name||void 0}function Fe(e,t){return t?"props":e.alternate?e.memoizedProps!==e.alternate.memoizedProps?"props":e.memoizedState!==e.alternate.memoizedState?"state":"parent":"unknown"}function Pe(e){if(e.length<2)return 0;let t=Date.now(),n=t-te,r=e.filter(c=>c>=n);if(r.length<2)return 0;let s=t-r[0];return s===0?0:r.length/(s/1e3)}function Be(e,t,n,r){if(e.size===0)return;let s=[],c=[],o=0;for(let[u,d]of e){let l=Pe(d.renderTimestamps),f=l>4||d.renderCount>20;s.push({componentName:u,renderCount:d.renderCount,totalDuration:Math.round(d.totalDuration*100)/100,avgDuration:d.renderCount>0?Math.round(d.totalDuration/d.renderCount*100)/100:0,lastRenderPhase:d.lastRenderPhase,lastRenderCause:d.lastRenderCause,renderVelocity:Math.round(l*100)/100,suspicious:f}),f&&c.push(u),o+=d.renderCount}s.sort((u,d)=>d.renderCount-u.renderCount);let i={eventId:m(),sessionId:n,timestamp:Date.now(),eventType:"render",profiles:s,snapshotWindowMs:te,totalRenders:o,suspiciousComponents:c};if(r){let u=r(i);u&&t(u)}else t(i);let a=Date.now();for(let[u,d]of e)a-d.lastRenderTime>xe?e.delete(u):(d.renderCount=0,d.totalDuration=0);if(e.size>ee){let u=[...e.entries()].sort((l,f)=>l[1].lastRenderTime-f[1].lastRenderTime),d=e.size-ee;for(let l=0;l<d;l++)e.delete(u[l][0])}}function re(e,t,n){let r=c=>{let o,i,a;if(c instanceof ErrorEvent)o=c.message||"Uncaught error",i=c.error?.stack,a=c.filename?`${c.filename}:${c.lineno}:${c.colno}`:void 0;else{let d=c.target;if(d&&d!==window){let l=d.tagName?.toLowerCase()??"unknown",f=d.src??d.src??d.href??"unknown";o=`Failed to load resource: <${l}> ${f}`}else return}let u={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"console",level:"error",message:`[Uncaught] ${o}`,args:[y(o,3)],stackTrace:i,sourceFile:a};if(n){let d=n(u);d&&e(d)}else e(u)},s=c=>{let o=c.reason,i,a;if(o instanceof Error)i=o.message,a=o.stack;else if(typeof o=="string")i=o;else try{i=JSON.stringify(o)}catch{i=String(o)}let u={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"console",level:"error",message:`[Unhandled Rejection] ${i}`,args:[y(o,3)],stackTrace:a,sourceFile:void 0};if(n){let d=n(u);d&&e(d)}else e(u)};return window.addEventListener("error",r,!0),window.addEventListener("unhandledrejection",s),()=>{window.removeEventListener("error",r,!0),window.removeEventListener("unhandledrejection",s)}}function se(e,t){let n=window.location.href;function r(a,u){let d=n;d!==a&&(n=a,e({eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"navigation",from:d,to:a,trigger:u}))}let s=history.pushState.bind(history),c=history.replaceState.bind(history);history.pushState=function(...a){s(...a),r(window.location.href,"pushState")},history.replaceState=function(...a){c(...a),r(window.location.href,"replaceState")};let o=()=>r(window.location.href,"popstate");window.addEventListener("popstate",o);let i=()=>r(window.location.href,"hashchange");return window.addEventListener("hashchange",i),()=>{history.pushState=s,history.replaceState=c,window.removeEventListener("popstate",o),window.removeEventListener("hashchange",i)}}function oe(e,t){let n=r=>{let s=r.target;if(!(s instanceof Element)||s.closest("[data-runtimescope]"))return;let c=qe(s),o=ze(s),i={eventId:m(),sessionId:t,timestamp:Date.now(),eventType:"ui",action:"click",target:c,...o&&{text:o}};e(i)};return document.addEventListener("click",n,!0),()=>{document.removeEventListener("click",n,!0)}}function qe(e){let t=e.tagName.toLowerCase();if(e.id)return`${t}#${e.id}`;let n=e.getAttribute("data-testid")??e.getAttribute("data-test-id");if(n)return`${t}[data-testid="${n}"]`;let r=e.getAttribute("role"),s=e.getAttribute("aria-label");if(r&&s)return`${t}[role="${r}"][aria-label="${s}"]`;let c=e.className;if(typeof c=="string"&&c.trim()){let i=c.split(/\s+/).find(a=>a.length>2&&!a.startsWith("_")&&!a.includes("__"));if(i)return`${t}.${i}`}let o=e.parentElement;if(o){let i=o.children,a=Array.from(i).filter(u=>u.tagName===e.tagName);if(a.length>1){let u=a.indexOf(e)+1;return`${t}:nth-child(${u})`}}return t}function ze(e){let t=e.getAttribute("aria-label");if(t)return t.slice(0,80);let n=e.innerText??e.textContent;if(!n)return;let r=n.trim().replace(/\s+/g," ");if(r.length!==0)return r.length>80?r.slice(0,77)+"...":r}var q="0.8.0",A=console.debug.bind(console),z=Symbol.for("__runtimescope_originals__");function Ue(){let e=globalThis;return e[z]||(e[z]={fetch:window.fetch,xhrOpen:XMLHttpRequest.prototype.open,xhrSend:XMLHttpRequest.prototype.send,xhrSetRequestHeader:XMLHttpRequest.prototype.setRequestHeader,consoleMethods:{log:console.log.bind(console),warn:console.warn.bind(console),error:console.error.bind(console),info:console.info.bind(console),debug:console.debug.bind(console),trace:console.trace.bind(console)}}),e[z]}var E=class{static get sessionId(){return this._sessionId}static get isConnected(){return this._state==="started"}static shouldSample(){if(this._sampleRate<1&&Math.random()>this._sampleRate)return!1;if(this._maxEventsPerSecond!==void 0){let t=Date.now();if(t-this._windowStart>=1e3&&(this._windowCount=0,this._windowStart=t),this._windowCount>=this._maxEventsPerSecond)return!1;this._windowCount++}return!0}static connect(t={}){if(t.enabled===!1)return;this._state==="started"&&(A("[RuntimeScope] Already connected \u2014 disconnecting before re-init"),this.disconnect());let n={serverUrl:t.serverUrl??t.endpoint??"ws://localhost:9090",appName:t.appName??"unknown",captureNetwork:t.captureNetwork??!0,captureConsole:t.captureConsole??!0,captureXhr:t.captureXhr??!0,captureBody:t.captureBody??!1,maxBodySize:t.maxBodySize??65536,capturePerformance:t.capturePerformance??!0,captureRenders:t.captureRenders??!0,captureNavigation:t.captureNavigation??!0,captureClicks:t.captureClicks??!0,stores:t.stores??{},beforeSend:t.beforeSend,redactHeaders:t.redactHeaders??["authorization","cookie"],batchSize:t.batchSize??50,flushIntervalMs:t.flushIntervalMs??100};Ue(),this._sessionId=$(),this._state="started",this.transport=new F({serverUrl:n.serverUrl,appName:n.appName,sessionId:this._sessionId,sdkVersion:q,authToken:t.authToken,batchSize:n.batchSize,flushIntervalMs:n.flushIntervalMs}),this._sampleRate=t.sampleRate??1,this._maxEventsPerSecond=t.maxEventsPerSecond,this._windowCount=0,this._windowStart=Date.now(),this._user=t.user,this.transport.connect(),A(`[RuntimeScope] SDK v${q} initializing \u2014 app: ${n.appName}, server: ${n.serverUrl}`);let r=o=>{o.eventType!=="session"&&o.eventType!=="custom"&&o.eventType!=="ui"&&!this.shouldSample()||this.transport?.send(o)};r({eventId:m(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"session",appName:n.appName,connectedAt:Date.now(),sdkVersion:q,buildMeta:t.buildMeta,user:this._user});let s=this._sessionId;this.transport.onCommand(o=>{this.handleCommand(o,r,s)}),n.captureNetwork&&this.restoreFns.push(W(r,this._sessionId,n.redactHeaders,{captureBody:n.captureBody,maxBodySize:n.maxBodySize,beforeSend:n.beforeSend})),n.captureXhr&&this.restoreFns.push(Q(r,this._sessionId,n.redactHeaders,{captureBody:n.captureBody,maxBodySize:n.maxBodySize,beforeSend:n.beforeSend})),n.captureConsole&&(this.restoreFns.push(G(r,this._sessionId,n.beforeSend)),this.restoreFns.push(re(r,this._sessionId,n.beforeSend))),Object.keys(n.stores).length>0&&this.restoreFns.push(Y(r,this._sessionId,n.stores,{beforeSend:n.beforeSend})),n.capturePerformance&&this.restoreFns.push(J(r,this._sessionId,{beforeSend:n.beforeSend})),n.captureRenders&&this.restoreFns.push(ne(r,this._sessionId,{beforeSend:n.beforeSend})),n.captureNavigation&&this.restoreFns.push(se(r,this._sessionId)),n.captureClicks&&this.restoreFns.push(oe(r,this._sessionId));let c=[n.captureNetwork&&"fetch",n.captureXhr&&"xhr",n.captureConsole&&"console, errors",Object.keys(n.stores).length>0&&"state",n.capturePerformance&&"performance",n.captureRenders&&"renders",n.captureNavigation&&"navigation",n.captureClicks&&"clicks"].filter(Boolean);A(`[RuntimeScope] Interceptors active \u2014 ${c.join(", ")}`),this._sampleRate<1&&A(`[RuntimeScope] Sampling at ${(this._sampleRate*100).toFixed(0)}%`),this._maxEventsPerSecond!==void 0&&A(`[RuntimeScope] Rate limited to ${this._maxEventsPerSecond} events/sec`)}static handleCommand(t,n,r){if(t.command==="capture_dom_snapshot"){let s=t.params?.maxSize??5e5,c=document.documentElement.outerHTML,o=c.length>s;o&&(c=c.slice(0,s));let i={eventId:m(),sessionId:r,timestamp:Date.now(),eventType:"dom_snapshot",html:c,url:window.location.href,viewport:{width:window.innerWidth,height:window.innerHeight},scrollPosition:{x:window.scrollX,y:window.scrollY},elementCount:document.querySelectorAll("*").length,truncated:o};n(i),this.transport?.sendCommandResponse(t.requestId,t.command,i)}else this.transport?.sendCommandResponse(t.requestId,t.command,{error:"Unknown command"})}static init(t={}){return this.connect(t)}static track(t,n){if(!this.transport||!this._sessionId)return;let r={eventId:m(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"custom",name:t,properties:n};this.transport.send(r)}static setUser(t){this._user=t??void 0,this.transport&&this._sessionId&&this.transport.send({eventId:m(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"session",appName:"user_update",connectedAt:Date.now(),sdkVersion:q,user:this._user})}static addBreadcrumb(t,n){if(!this.transport||!this._sessionId)return;let r={eventId:m(),sessionId:this._sessionId,timestamp:Date.now(),eventType:"ui",action:"breadcrumb",target:"manual",text:t,...n&&{data:n}};this.transport.send(r)}static disconnect(){for(let n of this.restoreFns)try{n()}catch{}this.restoreFns=[];let t=globalThis[z];if(t){window.fetch!==t.fetch&&(window.fetch=t.fetch);for(let[n,r]of Object.entries(t.consoleMethods)){let s=console;s[n]!==r&&(s[n]=r)}}this.transport?.disconnect(),this.transport=null,this._sessionId=null,this._state="stopped"}};p(E,"transport",null),p(E,"restoreFns",[]),p(E,"_sessionId",null),p(E,"_state","stopped"),p(E,"_sampleRate",1),p(E,"_maxEventsPerSecond"),p(E,"_windowCount",0),p(E,"_windowStart",0),p(E,"_user");var je=E;return pe(Xe);})();
|
|
4
4
|
if(typeof RuntimeScope!=="undefined"&&RuntimeScope.RuntimeScope){RuntimeScope=RuntimeScope.RuntimeScope;}
|
|
5
5
|
//# sourceMappingURL=index.global.js.map
|