@getlimelight/sdk 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -255,9 +255,7 @@ var SENSITIVE_HEADERS = [
255
255
  "x-secret",
256
256
  "bearer"
257
257
  ];
258
- var DEFAULT_PORT = 9090;
259
- var WS_PATH = "/limelight";
260
- var SDK_VERSION = true ? "0.2.0" : "test-version";
258
+ var SDK_VERSION = true ? "0.2.1" : "test-version";
261
259
  var RENDER_THRESHOLDS = {
262
260
  HOT_VELOCITY: 5,
263
261
  HIGH_RENDER_COUNT: 50,
@@ -1638,7 +1636,7 @@ var LimelightClient = class {
1638
1636
  const isEnabled = config.enabled ?? isDevelopment();
1639
1637
  this.config = {
1640
1638
  appName: "Limelight App",
1641
- serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,
1639
+ serverUrl: "wss://api.getlimelight.io/limelight",
1642
1640
  enabled: isEnabled,
1643
1641
  enableNetworkInspector: true,
1644
1642
  enableConsole: true,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["export { Limelight } from \"./limelight\";\nexport type { LimelightConfig } from \"./types\";\nexport * from \"./types\";\n","import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n\n/**\n * Thresholds for suspicious render detection.\n */\nexport const RENDER_THRESHOLDS = {\n HOT_VELOCITY: 5,\n HIGH_RENDER_COUNT: 50,\n VELOCITY_WINDOW_MS: 2000,\n SNAPSHOT_INTERVAL_MS: 1000,\n MIN_DELTA_TO_EMIT: 1,\n MAX_PROP_KEYS_TO_TRACK: 20, // Don't track more than this many unique props\n MAX_PROP_CHANGES_PER_SNAPSHOT: 10, // Limit delta array size\n TOP_PROPS_TO_REPORT: 5, // Only report top N changed props\n} as const;\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","let counter = 0;\n\n/**\n * Generates a unique ID using timestamp + counter + random.\n * Handles high-frequency calls without collision.\n *\n * Format: `{base36-timestamp}{counter}-{random}`\n * Example: `lq2x5k0-a7b3`\n */\nexport const generateRenderId = (): string => {\n const timestamp = Date.now().toString(36);\n const count = (counter++).toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n\n // Reset counter periodically to keep IDs shorter\n if (counter > 1000) counter = 0;\n\n return `${timestamp}${count}-${random}`;\n};\n","import { RenderCauseType } from \"@/types/render\";\n\n/**\n * Creates an empty cause breakdown object with all render cause types initialized to zero.\n * @returns {Record<RenderCauseType, number>} An object with render cause types as keys and zero as values.\n */\nexport const createEmptyCauseBreakdown = (): Record<\n RenderCauseType,\n number\n> => {\n return {\n [RenderCauseType.STATE_CHANGE]: 0,\n [RenderCauseType.PROPS_CHANGE]: 0,\n [RenderCauseType.CONTEXT_CHANGE]: 0,\n [RenderCauseType.PARENT_RENDER]: 0,\n [RenderCauseType.FORCE_UPDATE]: 0,\n [RenderCauseType.UNKNOWN]: 0,\n };\n};\n","import { PropChangeStats } from \"@/types/render\";\n\n/**\n * Creates and returns an empty PropChangeStats object.\n * @returns {PropChangeStats} An object with initialized changeCount and referenceOnlyCount maps.\n */\nexport const createEmptyPropChangeStats = (): PropChangeStats => {\n return {\n changeCount: new Map(),\n referenceOnlyCount: new Map(),\n };\n};\n","// Global accessor for render interceptor (avoids hook requirements)\nlet globalGetTransactionId: (() => string | null) | null = null;\n\n/**\n * Gets the current transaction ID from anywhere (for render interceptor use).\n * Returns null if no provider is mounted or no transaction is active.\n * @return {string | null} The current transaction ID or null.\n */\nexport const getCurrentTransactionId = (): string | null => {\n return globalGetTransactionId?.() ?? null;\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n let responseData;\n\n const responseType = this.responseType || \"\";\n\n if (responseType === \"\" || responseType === \"text\") {\n responseData = this.responseText;\n } else if (\n responseType === \"blob\" ||\n responseType === \"arraybuffer\"\n ) {\n responseData = `[Binary Data: ${responseType}]`;\n } else if (responseType === \"json\") {\n responseData = this.response;\n } else {\n responseData = this.response;\n }\n\n const responseBody = serializeBody(\n responseData,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import {\n RenderPhase,\n RenderCauseType,\n RenderConfidence,\n ComponentType,\n MinimalFiber,\n ReactDevToolsHook,\n FiberTag,\n FiberFlags,\n ComponentProfile,\n PropChangeDetail,\n PropChangeSnapshot,\n ComponentProfileSnapshot,\n} from \"@/types/render\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n createEmptyPropChangeStats,\n generateRenderId,\n getCurrentTransactionId,\n isDevelopment,\n} from \"@/helpers\";\nimport { createEmptyCauseBreakdown } from \"@/helpers/render/createEmptyCauseBreakdown\";\nimport { RENDER_THRESHOLDS } from \"@/constants\";\n\n/**\n * Intercepts React renders via the DevTools global hook.\n */\nexport class RenderInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n private profiles = new Map<string, ComponentProfile>();\n private fiberToComponentId = new WeakMap<MinimalFiber, string>();\n private componentIdCounter = 0;\n\n private snapshotTimer: ReturnType<typeof setInterval> | null = null;\n\n private currentCommitComponents = new Set<string>();\n private componentsInCurrentCommit = 0;\n\n private originalHook: ReactDevToolsHook | null = null;\n\n private originalOnCommitFiberRoot:\n | ReactDevToolsHook[\"onCommitFiberRoot\"]\n | null = null;\n private originalOnCommitFiberUnmount:\n | ReactDevToolsHook[\"onCommitFiberUnmount\"]\n | null = null;\n\n private pendingUnmounts: ComponentProfile[] = [];\n\n constructor(\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string\n ) {\n this.sendMessage = sendMessage;\n this.getSessionId = getSessionId;\n }\n\n setup(config: LimelightConfig): void {\n if (this.isSetup) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n console.warn(\"[Limelight] Failed to install render hook\");\n return;\n }\n\n this.snapshotTimer = setInterval(() => {\n this.emitSnapshot();\n }, RENDER_THRESHOLDS.SNAPSHOT_INTERVAL_MS);\n\n this.isSetup = true;\n }\n\n private installHook(): boolean {\n const globalObj =\n typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : null;\n\n if (!globalObj) return false;\n\n const hookKey = \"__REACT_DEVTOOLS_GLOBAL_HOOK__\";\n const existingHook = (globalObj as any)[hookKey] as\n | ReactDevToolsHook\n | undefined;\n\n if (existingHook) {\n this.wrapExistingHook(existingHook);\n } else {\n this.createHook(globalObj, hookKey);\n }\n\n return true;\n }\n\n private wrapExistingHook(hook: ReactDevToolsHook): void {\n this.originalHook = hook;\n this.originalOnCommitFiberRoot = hook.onCommitFiberRoot?.bind(hook);\n this.originalOnCommitFiberUnmount = hook.onCommitFiberUnmount?.bind(hook);\n\n hook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {\n this.originalOnCommitFiberRoot?.(rendererID, root, priorityLevel);\n this.handleCommitFiberRoot(rendererID, root);\n };\n\n hook.onCommitFiberUnmount = (rendererID, fiber) => {\n this.originalOnCommitFiberUnmount?.(rendererID, fiber);\n this.handleCommitFiberUnmount(rendererID, fiber);\n };\n }\n\n private createHook(globalObj: any, hookKey: string): void {\n const renderers = new Map<number, any>();\n let rendererIdCounter = 0;\n\n const hook: ReactDevToolsHook = {\n supportsFiber: true,\n inject: (renderer) => {\n const id = ++rendererIdCounter;\n renderers.set(id, renderer);\n return id;\n },\n onCommitFiberRoot: (rendererID, root, priorityLevel) => {\n this.handleCommitFiberRoot(rendererID, root);\n },\n onCommitFiberUnmount: (rendererID, fiber) => {\n this.handleCommitFiberUnmount(rendererID, fiber);\n },\n };\n\n globalObj[hookKey] = hook;\n }\n /**\n * Handles a fiber root commit - walks tree and ACCUMULATES into profiles.\n * Two-pass: first count components, then accumulate with distributed cost.\n */\n private handleCommitFiberRoot(\n _rendererID: number,\n root: { current: MinimalFiber }\n ): void {\n this.currentCommitComponents.clear();\n this.componentsInCurrentCommit = 0;\n\n try {\n this.countRenderedComponents(root.current);\n this.walkFiberTree(root.current, null, 0);\n } catch (error) {\n if (isDevelopment()) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n */\n private countRenderedComponents(fiber: MinimalFiber | null): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n this.componentsInCurrentCommit++;\n }\n\n this.countRenderedComponents(fiber.child);\n this.countRenderedComponents(fiber.sibling);\n }\n\n private handleCommitFiberUnmount(\n _rendererID: number,\n fiber: MinimalFiber\n ): void {\n if (!this.isUserComponent(fiber)) return;\n\n const componentId = this.fiberToComponentId.get(fiber);\n if (!componentId) return;\n\n const profile = this.profiles.get(componentId);\n if (profile) {\n profile.unmountedAt = Date.now();\n this.pendingUnmounts.push(profile);\n this.profiles.delete(componentId);\n }\n }\n\n /**\n * Walks fiber tree and accumulates render stats into profiles.\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number\n ): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n const componentId = this.getOrCreateComponentId(fiber);\n this.accumulateRender(fiber, componentId, parentComponentId, depth);\n this.currentCommitComponents.add(componentId);\n parentComponentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, parentComponentId, depth + 1);\n this.walkFiberTree(fiber.sibling, parentComponentId, depth);\n }\n\n /**\n * Core accumulation logic - this is where we build up the profile.\n */\n private accumulateRender(\n fiber: MinimalFiber,\n componentId: string,\n parentComponentId: string | null,\n depth: number\n ): void {\n const now = Date.now();\n const cause = this.inferRenderCause(fiber, parentComponentId);\n\n const renderCost =\n this.componentsInCurrentCommit > 0\n ? 1 / this.componentsInCurrentCommit\n : 1;\n\n let profile = this.profiles.get(componentId);\n\n if (!profile) {\n profile = {\n id: generateRenderId(),\n componentId,\n componentName: this.getComponentName(fiber),\n componentType: this.getComponentType(fiber),\n mountedAt: now,\n totalRenders: 0,\n totalRenderCost: 0,\n velocityWindowStart: now,\n velocityWindowCount: 0,\n causeBreakdown: createEmptyCauseBreakdown(),\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n lastEmittedRenderCount: 0,\n lastEmittedRenderCost: 0,\n lastEmitTime: now,\n parentCounts: new Map(),\n depth,\n isSuspicious: false,\n // NEW\n propChangeStats: createEmptyPropChangeStats(),\n propChangeDelta: [],\n };\n this.profiles.set(componentId, profile);\n }\n\n profile.totalRenders++;\n profile.totalRenderCost += renderCost;\n\n profile.causeBreakdown[cause.type]++;\n profile.causeDeltaBreakdown[cause.type]++;\n\n if (cause.type === RenderCauseType.PROPS_CHANGE && cause.propChanges) {\n this.accumulatePropChanges(profile, cause.propChanges);\n }\n\n const transactionId = getCurrentTransactionId();\n\n if (transactionId) {\n profile.lastTransactionId = transactionId;\n }\n\n if (parentComponentId) {\n const count = (profile.parentCounts.get(parentComponentId) ?? 0) + 1;\n profile.parentCounts.set(parentComponentId, count);\n\n if (\n !profile.primaryParentId ||\n count > (profile.parentCounts.get(profile.primaryParentId) ?? 0)\n ) {\n profile.primaryParentId = parentComponentId;\n }\n }\n\n profile.depth = depth;\n\n const windowStart = now - RENDER_THRESHOLDS.VELOCITY_WINDOW_MS;\n if (profile.velocityWindowStart < windowStart) {\n profile.velocityWindowStart = now;\n profile.velocityWindowCount = 1;\n } else {\n profile.velocityWindowCount++;\n }\n\n this.updateSuspiciousFlag(profile);\n }\n\n /**\n * NEW: Accumulate prop change details into the profile.\n */\n private accumulatePropChanges(\n profile: ComponentProfile,\n changes: PropChangeDetail[]\n ): void {\n const stats = profile.propChangeStats;\n\n for (const change of changes) {\n if (\n stats.changeCount.size >= RENDER_THRESHOLDS.MAX_PROP_KEYS_TO_TRACK &&\n !stats.changeCount.has(change.key)\n ) {\n continue;\n }\n\n stats.changeCount.set(\n change.key,\n (stats.changeCount.get(change.key) ?? 0) + 1\n );\n\n if (change.referenceOnly) {\n stats.referenceOnlyCount.set(\n change.key,\n (stats.referenceOnlyCount.get(change.key) ?? 0) + 1\n );\n }\n }\n\n if (\n profile.propChangeDelta.length <\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT\n ) {\n profile.propChangeDelta.push(\n ...changes.slice(\n 0,\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT -\n profile.propChangeDelta.length\n )\n );\n }\n }\n\n /**\n * Build prop change snapshot for emission.\n */\n private buildPropChangeSnapshot(\n profile: ComponentProfile\n ): PropChangeSnapshot | undefined {\n const stats = profile.propChangeStats;\n\n if (stats.changeCount.size === 0) {\n return undefined;\n }\n\n const sorted = Array.from(stats.changeCount.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, RENDER_THRESHOLDS.TOP_PROPS_TO_REPORT);\n\n const topChangedProps = sorted.map(([key, count]) => {\n const refOnlyCount = stats.referenceOnlyCount.get(key) ?? 0;\n return {\n key,\n count,\n referenceOnlyPercent:\n count > 0 ? Math.round((refOnlyCount / count) * 100) : 0,\n };\n });\n\n return { topChangedProps };\n }\n\n private updateSuspiciousFlag(profile: ComponentProfile): void {\n const velocity = this.calculateVelocity(profile);\n\n if (velocity > RENDER_THRESHOLDS.HOT_VELOCITY) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High render velocity: ${velocity.toFixed(\n 1\n )}/sec`;\n } else if (profile.totalRenders > RENDER_THRESHOLDS.HIGH_RENDER_COUNT) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High total renders: ${profile.totalRenders}`;\n } else {\n profile.isSuspicious = false;\n profile.suspiciousReason = undefined;\n }\n }\n\n /**\n * Calculates renders per second from velocity window.\n * Cheap: just count / window duration, no array operations.\n */\n private calculateVelocity(profile: ComponentProfile): number {\n const now = Date.now();\n const windowAge = now - profile.velocityWindowStart;\n\n if (windowAge > RENDER_THRESHOLDS.VELOCITY_WINDOW_MS) {\n return 0;\n }\n\n const effectiveWindowMs = Math.max(windowAge, 100);\n return (profile.velocityWindowCount / effectiveWindowMs) * 1000;\n }\n\n /**\n * Emits a snapshot of all profiles with deltas.\n */\n private emitSnapshot(): void {\n const now = Date.now();\n const snapshots: ComponentProfileSnapshot[] = [];\n\n for (const profile of this.profiles.values()) {\n const rendersDelta =\n profile.totalRenders - profile.lastEmittedRenderCount;\n\n if (\n rendersDelta < RENDER_THRESHOLDS.MIN_DELTA_TO_EMIT &&\n !profile.isSuspicious\n ) {\n continue;\n }\n\n const velocity = this.calculateVelocity(profile);\n const isMount = profile.lastEmittedRenderCount === 0;\n const renderCostDelta =\n profile.totalRenderCost - profile.lastEmittedRenderCost;\n\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost: profile.totalRenderCost / profile.totalRenders,\n rendersDelta,\n renderCostDelta,\n renderVelocity: velocity,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: { ...profile.causeDeltaBreakdown },\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: isMount ? RenderPhase.MOUNT : RenderPhase.UPDATE,\n mountedAt: profile.mountedAt,\n propChanges,\n });\n\n profile.lastEmittedRenderCount = profile.totalRenders;\n profile.lastEmittedRenderCost = profile.totalRenderCost;\n profile.lastEmitTime = now;\n profile.causeDeltaBreakdown = createEmptyCauseBreakdown();\n profile.propChangeDelta = [];\n }\n\n for (const profile of this.pendingUnmounts) {\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost:\n profile.totalRenderCost / Math.max(profile.totalRenders, 1),\n rendersDelta: 0,\n renderCostDelta: 0,\n renderVelocity: 0,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: RenderPhase.UNMOUNT,\n mountedAt: profile.mountedAt,\n unmountedAt: profile.unmountedAt,\n propChanges,\n });\n }\n this.pendingUnmounts = [];\n\n if (snapshots.length === 0) return;\n\n let message: LimelightMessage = {\n phase: \"RENDER_SNAPSHOT\",\n sessionId: this.getSessionId(),\n timestamp: now,\n profiles: snapshots,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(message);\n if (!modified) return;\n message = modified;\n }\n\n this.sendMessage(message);\n }\n\n /**\n * Now returns prop change details when applicable.\n */\n private inferRenderCause(\n fiber: MinimalFiber,\n parentComponentId: string | null\n ): {\n type: RenderCauseType;\n confidence: RenderConfidence;\n triggerId?: string;\n propChanges?: PropChangeDetail[]; // NEW\n } {\n const alternate = fiber.alternate;\n\n if (!alternate) {\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.HIGH,\n };\n }\n\n if (\n parentComponentId &&\n this.currentCommitComponents.has(parentComponentId)\n ) {\n const prevProps = alternate.memoizedProps;\n const nextProps = fiber.memoizedProps;\n const propsChanged = prevProps !== nextProps;\n\n if (propsChanged) {\n const propChanges = this.diffProps(prevProps, nextProps);\n\n return {\n type: RenderCauseType.PROPS_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n propChanges,\n };\n }\n\n return {\n type: RenderCauseType.PARENT_RENDER,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n };\n }\n\n // State change\n if (fiber.memoizedState !== alternate.memoizedState) {\n return {\n type: RenderCauseType.STATE_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n };\n }\n\n if (fiber.memoizedProps !== alternate.memoizedProps) {\n return {\n type: RenderCauseType.CONTEXT_CHANGE,\n confidence: RenderConfidence.LOW,\n };\n }\n\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.UNKNOWN,\n };\n }\n\n /**\n * Diff props to find which keys changed and whether it's reference-only.\n * This is the key insight generator.\n */\n private diffProps(\n prevProps: Record<string, any> | null,\n nextProps: Record<string, any> | null\n ): PropChangeDetail[] {\n if (!prevProps || !nextProps) {\n return [];\n }\n\n const changes: PropChangeDetail[] = [];\n const allKeys = new Set([\n ...Object.keys(prevProps),\n ...Object.keys(nextProps),\n ]);\n\n const skipKeys = new Set([\"children\", \"key\", \"ref\"]);\n\n for (const key of allKeys) {\n if (skipKeys.has(key)) continue;\n\n const prevValue = prevProps[key];\n const nextValue = nextProps[key];\n\n if (prevValue === nextValue) {\n continue;\n }\n\n const referenceOnly = this.isShallowEqual(prevValue, nextValue);\n\n changes.push({ key, referenceOnly });\n\n if (changes.length >= 10) {\n break;\n }\n }\n\n return changes;\n }\n\n /**\n * Shallow equality check to determine if a prop is reference-only change.\n * We only go one level deep to keep it fast.\n */\n private isShallowEqual(a: any, b: any): boolean {\n // Same reference (already checked, but for safety)\n if (a === b) return true;\n\n // Different types\n if (typeof a !== typeof b) return false;\n\n // Null checks\n if (a === null || b === null) return false;\n\n // Functions - can't easily compare, assume different\n // But if they're both functions, it's likely a reference-only change\n // (same callback recreated)\n if (typeof a === \"function\" && typeof b === \"function\") {\n // We can't compare function bodies easily, but this is almost always\n // a reference-only change (inline callback recreated)\n return true; // Treat as reference-only\n }\n\n // Arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n return true;\n }\n\n return a === b;\n }\n\n private isUserComponent(fiber: MinimalFiber): boolean {\n const tag = fiber.tag;\n return (\n tag === FiberTag.FunctionComponent ||\n tag === FiberTag.ClassComponent ||\n tag === FiberTag.ForwardRef ||\n tag === FiberTag.MemoComponent ||\n tag === FiberTag.SimpleMemoComponent\n );\n }\n\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n private getOrCreateComponentId(fiber: MinimalFiber): string {\n let id = this.fiberToComponentId.get(fiber);\n if (id) return id;\n\n if (fiber.alternate) {\n id = this.fiberToComponentId.get(fiber.alternate);\n if (id) {\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n }\n\n id = `c_${++this.componentIdCounter}`;\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n\n private getComponentName(fiber: MinimalFiber): string {\n const type = fiber.type;\n if (!type) return \"Unknown\";\n\n if (typeof type === \"function\") {\n return type.displayName || type.name || \"Anonymous\";\n }\n\n if (typeof type === \"object\" && type !== null) {\n if (type.displayName) return type.displayName;\n if (type.render)\n return type.render.displayName || type.render.name || \"ForwardRef\";\n if (type.type) {\n const inner = type.type;\n return inner.displayName || inner.name || \"Memo\";\n }\n }\n\n return \"Unknown\";\n }\n\n private getComponentType(fiber: MinimalFiber): ComponentType {\n switch (fiber.tag) {\n case FiberTag.FunctionComponent:\n return \"function\";\n case FiberTag.ClassComponent:\n return \"class\";\n case FiberTag.ForwardRef:\n return \"forwardRef\";\n case FiberTag.MemoComponent:\n case FiberTag.SimpleMemoComponent:\n return \"memo\";\n default:\n return \"unknown\";\n }\n }\n\n /**\n * Force emit current state (useful for debugging or on-demand refresh).\n */\n forceEmit(): void {\n this.emitSnapshot();\n }\n\n /**\n * Get current profile for a component (useful for debugging).\n */\n getProfile(componentId: string): ComponentProfile | undefined {\n return this.profiles.get(componentId);\n }\n\n /**\n * Get all suspicious components.\n */\n getSuspiciousComponents(): ComponentProfile[] {\n return Array.from(this.profiles.values()).filter((p) => p.isSuspicious);\n }\n\n cleanup(): void {\n if (!this.isSetup) return;\n\n this.emitSnapshot();\n\n if (this.snapshotTimer) {\n clearInterval(this.snapshotTimer);\n this.snapshotTimer = null;\n }\n\n if (this.originalHook) {\n if (this.originalOnCommitFiberRoot) {\n this.originalHook.onCommitFiberRoot = this.originalOnCommitFiberRoot;\n }\n if (this.originalOnCommitFiberUnmount) {\n this.originalHook.onCommitFiberUnmount =\n this.originalOnCommitFiberUnmount;\n }\n }\n\n this.originalHook = null;\n this.originalOnCommitFiberRoot = null;\n this.originalOnCommitFiberUnmount = null;\n this.profiles.clear();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n this.config = null;\n this.isSetup = false;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, SDK_VERSION, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.renderInterceptor = new RenderInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, console, and render interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n enableRenderInspector: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n\n if (this.config.enableRenderInspector) {\n this.renderInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["export { Limelight } from \"./limelight\";\nexport type { LimelightConfig } from \"./types\";\nexport * from \"./types\";\n","import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n\n/**\n * Thresholds for suspicious render detection.\n */\nexport const RENDER_THRESHOLDS = {\n HOT_VELOCITY: 5,\n HIGH_RENDER_COUNT: 50,\n VELOCITY_WINDOW_MS: 2000,\n SNAPSHOT_INTERVAL_MS: 1000,\n MIN_DELTA_TO_EMIT: 1,\n MAX_PROP_KEYS_TO_TRACK: 20, // Don't track more than this many unique props\n MAX_PROP_CHANGES_PER_SNAPSHOT: 10, // Limit delta array size\n TOP_PROPS_TO_REPORT: 5, // Only report top N changed props\n} as const;\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","let counter = 0;\n\n/**\n * Generates a unique ID using timestamp + counter + random.\n * Handles high-frequency calls without collision.\n *\n * Format: `{base36-timestamp}{counter}-{random}`\n * Example: `lq2x5k0-a7b3`\n */\nexport const generateRenderId = (): string => {\n const timestamp = Date.now().toString(36);\n const count = (counter++).toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n\n // Reset counter periodically to keep IDs shorter\n if (counter > 1000) counter = 0;\n\n return `${timestamp}${count}-${random}`;\n};\n","import { RenderCauseType } from \"@/types/render\";\n\n/**\n * Creates an empty cause breakdown object with all render cause types initialized to zero.\n * @returns {Record<RenderCauseType, number>} An object with render cause types as keys and zero as values.\n */\nexport const createEmptyCauseBreakdown = (): Record<\n RenderCauseType,\n number\n> => {\n return {\n [RenderCauseType.STATE_CHANGE]: 0,\n [RenderCauseType.PROPS_CHANGE]: 0,\n [RenderCauseType.CONTEXT_CHANGE]: 0,\n [RenderCauseType.PARENT_RENDER]: 0,\n [RenderCauseType.FORCE_UPDATE]: 0,\n [RenderCauseType.UNKNOWN]: 0,\n };\n};\n","import { PropChangeStats } from \"@/types/render\";\n\n/**\n * Creates and returns an empty PropChangeStats object.\n * @returns {PropChangeStats} An object with initialized changeCount and referenceOnlyCount maps.\n */\nexport const createEmptyPropChangeStats = (): PropChangeStats => {\n return {\n changeCount: new Map(),\n referenceOnlyCount: new Map(),\n };\n};\n","// Global accessor for render interceptor (avoids hook requirements)\nlet globalGetTransactionId: (() => string | null) | null = null;\n\n/**\n * Gets the current transaction ID from anywhere (for render interceptor use).\n * Returns null if no provider is mounted or no transaction is active.\n * @return {string | null} The current transaction ID or null.\n */\nexport const getCurrentTransactionId = (): string | null => {\n return globalGetTransactionId?.() ?? null;\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n let responseData;\n\n const responseType = this.responseType || \"\";\n\n if (responseType === \"\" || responseType === \"text\") {\n responseData = this.responseText;\n } else if (\n responseType === \"blob\" ||\n responseType === \"arraybuffer\"\n ) {\n responseData = `[Binary Data: ${responseType}]`;\n } else if (responseType === \"json\") {\n responseData = this.response;\n } else {\n responseData = this.response;\n }\n\n const responseBody = serializeBody(\n responseData,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import {\n RenderPhase,\n RenderCauseType,\n RenderConfidence,\n ComponentType,\n MinimalFiber,\n ReactDevToolsHook,\n FiberTag,\n FiberFlags,\n ComponentProfile,\n PropChangeDetail,\n PropChangeSnapshot,\n ComponentProfileSnapshot,\n} from \"@/types/render\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n createEmptyPropChangeStats,\n generateRenderId,\n getCurrentTransactionId,\n isDevelopment,\n} from \"@/helpers\";\nimport { createEmptyCauseBreakdown } from \"@/helpers/render/createEmptyCauseBreakdown\";\nimport { RENDER_THRESHOLDS } from \"@/constants\";\n\n/**\n * Intercepts React renders via the DevTools global hook.\n */\nexport class RenderInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n private profiles = new Map<string, ComponentProfile>();\n private fiberToComponentId = new WeakMap<MinimalFiber, string>();\n private componentIdCounter = 0;\n\n private snapshotTimer: ReturnType<typeof setInterval> | null = null;\n\n private currentCommitComponents = new Set<string>();\n private componentsInCurrentCommit = 0;\n\n private originalHook: ReactDevToolsHook | null = null;\n\n private originalOnCommitFiberRoot:\n | ReactDevToolsHook[\"onCommitFiberRoot\"]\n | null = null;\n private originalOnCommitFiberUnmount:\n | ReactDevToolsHook[\"onCommitFiberUnmount\"]\n | null = null;\n\n private pendingUnmounts: ComponentProfile[] = [];\n\n constructor(\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string\n ) {\n this.sendMessage = sendMessage;\n this.getSessionId = getSessionId;\n }\n\n setup(config: LimelightConfig): void {\n if (this.isSetup) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n console.warn(\"[Limelight] Failed to install render hook\");\n return;\n }\n\n this.snapshotTimer = setInterval(() => {\n this.emitSnapshot();\n }, RENDER_THRESHOLDS.SNAPSHOT_INTERVAL_MS);\n\n this.isSetup = true;\n }\n\n private installHook(): boolean {\n const globalObj =\n typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : null;\n\n if (!globalObj) return false;\n\n const hookKey = \"__REACT_DEVTOOLS_GLOBAL_HOOK__\";\n const existingHook = (globalObj as any)[hookKey] as\n | ReactDevToolsHook\n | undefined;\n\n if (existingHook) {\n this.wrapExistingHook(existingHook);\n } else {\n this.createHook(globalObj, hookKey);\n }\n\n return true;\n }\n\n private wrapExistingHook(hook: ReactDevToolsHook): void {\n this.originalHook = hook;\n this.originalOnCommitFiberRoot = hook.onCommitFiberRoot?.bind(hook);\n this.originalOnCommitFiberUnmount = hook.onCommitFiberUnmount?.bind(hook);\n\n hook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {\n this.originalOnCommitFiberRoot?.(rendererID, root, priorityLevel);\n this.handleCommitFiberRoot(rendererID, root);\n };\n\n hook.onCommitFiberUnmount = (rendererID, fiber) => {\n this.originalOnCommitFiberUnmount?.(rendererID, fiber);\n this.handleCommitFiberUnmount(rendererID, fiber);\n };\n }\n\n private createHook(globalObj: any, hookKey: string): void {\n const renderers = new Map<number, any>();\n let rendererIdCounter = 0;\n\n const hook: ReactDevToolsHook = {\n supportsFiber: true,\n inject: (renderer) => {\n const id = ++rendererIdCounter;\n renderers.set(id, renderer);\n return id;\n },\n onCommitFiberRoot: (rendererID, root, priorityLevel) => {\n this.handleCommitFiberRoot(rendererID, root);\n },\n onCommitFiberUnmount: (rendererID, fiber) => {\n this.handleCommitFiberUnmount(rendererID, fiber);\n },\n };\n\n globalObj[hookKey] = hook;\n }\n /**\n * Handles a fiber root commit - walks tree and ACCUMULATES into profiles.\n * Two-pass: first count components, then accumulate with distributed cost.\n */\n private handleCommitFiberRoot(\n _rendererID: number,\n root: { current: MinimalFiber }\n ): void {\n this.currentCommitComponents.clear();\n this.componentsInCurrentCommit = 0;\n\n try {\n this.countRenderedComponents(root.current);\n this.walkFiberTree(root.current, null, 0);\n } catch (error) {\n if (isDevelopment()) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n */\n private countRenderedComponents(fiber: MinimalFiber | null): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n this.componentsInCurrentCommit++;\n }\n\n this.countRenderedComponents(fiber.child);\n this.countRenderedComponents(fiber.sibling);\n }\n\n private handleCommitFiberUnmount(\n _rendererID: number,\n fiber: MinimalFiber\n ): void {\n if (!this.isUserComponent(fiber)) return;\n\n const componentId = this.fiberToComponentId.get(fiber);\n if (!componentId) return;\n\n const profile = this.profiles.get(componentId);\n if (profile) {\n profile.unmountedAt = Date.now();\n this.pendingUnmounts.push(profile);\n this.profiles.delete(componentId);\n }\n }\n\n /**\n * Walks fiber tree and accumulates render stats into profiles.\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number\n ): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n const componentId = this.getOrCreateComponentId(fiber);\n this.accumulateRender(fiber, componentId, parentComponentId, depth);\n this.currentCommitComponents.add(componentId);\n parentComponentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, parentComponentId, depth + 1);\n this.walkFiberTree(fiber.sibling, parentComponentId, depth);\n }\n\n /**\n * Core accumulation logic - this is where we build up the profile.\n */\n private accumulateRender(\n fiber: MinimalFiber,\n componentId: string,\n parentComponentId: string | null,\n depth: number\n ): void {\n const now = Date.now();\n const cause = this.inferRenderCause(fiber, parentComponentId);\n\n const renderCost =\n this.componentsInCurrentCommit > 0\n ? 1 / this.componentsInCurrentCommit\n : 1;\n\n let profile = this.profiles.get(componentId);\n\n if (!profile) {\n profile = {\n id: generateRenderId(),\n componentId,\n componentName: this.getComponentName(fiber),\n componentType: this.getComponentType(fiber),\n mountedAt: now,\n totalRenders: 0,\n totalRenderCost: 0,\n velocityWindowStart: now,\n velocityWindowCount: 0,\n causeBreakdown: createEmptyCauseBreakdown(),\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n lastEmittedRenderCount: 0,\n lastEmittedRenderCost: 0,\n lastEmitTime: now,\n parentCounts: new Map(),\n depth,\n isSuspicious: false,\n // NEW\n propChangeStats: createEmptyPropChangeStats(),\n propChangeDelta: [],\n };\n this.profiles.set(componentId, profile);\n }\n\n profile.totalRenders++;\n profile.totalRenderCost += renderCost;\n\n profile.causeBreakdown[cause.type]++;\n profile.causeDeltaBreakdown[cause.type]++;\n\n if (cause.type === RenderCauseType.PROPS_CHANGE && cause.propChanges) {\n this.accumulatePropChanges(profile, cause.propChanges);\n }\n\n const transactionId = getCurrentTransactionId();\n\n if (transactionId) {\n profile.lastTransactionId = transactionId;\n }\n\n if (parentComponentId) {\n const count = (profile.parentCounts.get(parentComponentId) ?? 0) + 1;\n profile.parentCounts.set(parentComponentId, count);\n\n if (\n !profile.primaryParentId ||\n count > (profile.parentCounts.get(profile.primaryParentId) ?? 0)\n ) {\n profile.primaryParentId = parentComponentId;\n }\n }\n\n profile.depth = depth;\n\n const windowStart = now - RENDER_THRESHOLDS.VELOCITY_WINDOW_MS;\n if (profile.velocityWindowStart < windowStart) {\n profile.velocityWindowStart = now;\n profile.velocityWindowCount = 1;\n } else {\n profile.velocityWindowCount++;\n }\n\n this.updateSuspiciousFlag(profile);\n }\n\n /**\n * NEW: Accumulate prop change details into the profile.\n */\n private accumulatePropChanges(\n profile: ComponentProfile,\n changes: PropChangeDetail[]\n ): void {\n const stats = profile.propChangeStats;\n\n for (const change of changes) {\n if (\n stats.changeCount.size >= RENDER_THRESHOLDS.MAX_PROP_KEYS_TO_TRACK &&\n !stats.changeCount.has(change.key)\n ) {\n continue;\n }\n\n stats.changeCount.set(\n change.key,\n (stats.changeCount.get(change.key) ?? 0) + 1\n );\n\n if (change.referenceOnly) {\n stats.referenceOnlyCount.set(\n change.key,\n (stats.referenceOnlyCount.get(change.key) ?? 0) + 1\n );\n }\n }\n\n if (\n profile.propChangeDelta.length <\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT\n ) {\n profile.propChangeDelta.push(\n ...changes.slice(\n 0,\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT -\n profile.propChangeDelta.length\n )\n );\n }\n }\n\n /**\n * Build prop change snapshot for emission.\n */\n private buildPropChangeSnapshot(\n profile: ComponentProfile\n ): PropChangeSnapshot | undefined {\n const stats = profile.propChangeStats;\n\n if (stats.changeCount.size === 0) {\n return undefined;\n }\n\n const sorted = Array.from(stats.changeCount.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, RENDER_THRESHOLDS.TOP_PROPS_TO_REPORT);\n\n const topChangedProps = sorted.map(([key, count]) => {\n const refOnlyCount = stats.referenceOnlyCount.get(key) ?? 0;\n return {\n key,\n count,\n referenceOnlyPercent:\n count > 0 ? Math.round((refOnlyCount / count) * 100) : 0,\n };\n });\n\n return { topChangedProps };\n }\n\n private updateSuspiciousFlag(profile: ComponentProfile): void {\n const velocity = this.calculateVelocity(profile);\n\n if (velocity > RENDER_THRESHOLDS.HOT_VELOCITY) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High render velocity: ${velocity.toFixed(\n 1\n )}/sec`;\n } else if (profile.totalRenders > RENDER_THRESHOLDS.HIGH_RENDER_COUNT) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High total renders: ${profile.totalRenders}`;\n } else {\n profile.isSuspicious = false;\n profile.suspiciousReason = undefined;\n }\n }\n\n /**\n * Calculates renders per second from velocity window.\n * Cheap: just count / window duration, no array operations.\n */\n private calculateVelocity(profile: ComponentProfile): number {\n const now = Date.now();\n const windowAge = now - profile.velocityWindowStart;\n\n if (windowAge > RENDER_THRESHOLDS.VELOCITY_WINDOW_MS) {\n return 0;\n }\n\n const effectiveWindowMs = Math.max(windowAge, 100);\n return (profile.velocityWindowCount / effectiveWindowMs) * 1000;\n }\n\n /**\n * Emits a snapshot of all profiles with deltas.\n */\n private emitSnapshot(): void {\n const now = Date.now();\n const snapshots: ComponentProfileSnapshot[] = [];\n\n for (const profile of this.profiles.values()) {\n const rendersDelta =\n profile.totalRenders - profile.lastEmittedRenderCount;\n\n if (\n rendersDelta < RENDER_THRESHOLDS.MIN_DELTA_TO_EMIT &&\n !profile.isSuspicious\n ) {\n continue;\n }\n\n const velocity = this.calculateVelocity(profile);\n const isMount = profile.lastEmittedRenderCount === 0;\n const renderCostDelta =\n profile.totalRenderCost - profile.lastEmittedRenderCost;\n\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost: profile.totalRenderCost / profile.totalRenders,\n rendersDelta,\n renderCostDelta,\n renderVelocity: velocity,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: { ...profile.causeDeltaBreakdown },\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: isMount ? RenderPhase.MOUNT : RenderPhase.UPDATE,\n mountedAt: profile.mountedAt,\n propChanges,\n });\n\n profile.lastEmittedRenderCount = profile.totalRenders;\n profile.lastEmittedRenderCost = profile.totalRenderCost;\n profile.lastEmitTime = now;\n profile.causeDeltaBreakdown = createEmptyCauseBreakdown();\n profile.propChangeDelta = [];\n }\n\n for (const profile of this.pendingUnmounts) {\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost:\n profile.totalRenderCost / Math.max(profile.totalRenders, 1),\n rendersDelta: 0,\n renderCostDelta: 0,\n renderVelocity: 0,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: RenderPhase.UNMOUNT,\n mountedAt: profile.mountedAt,\n unmountedAt: profile.unmountedAt,\n propChanges,\n });\n }\n this.pendingUnmounts = [];\n\n if (snapshots.length === 0) return;\n\n let message: LimelightMessage = {\n phase: \"RENDER_SNAPSHOT\",\n sessionId: this.getSessionId(),\n timestamp: now,\n profiles: snapshots,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(message);\n if (!modified) return;\n message = modified;\n }\n\n this.sendMessage(message);\n }\n\n /**\n * Now returns prop change details when applicable.\n */\n private inferRenderCause(\n fiber: MinimalFiber,\n parentComponentId: string | null\n ): {\n type: RenderCauseType;\n confidence: RenderConfidence;\n triggerId?: string;\n propChanges?: PropChangeDetail[]; // NEW\n } {\n const alternate = fiber.alternate;\n\n if (!alternate) {\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.HIGH,\n };\n }\n\n if (\n parentComponentId &&\n this.currentCommitComponents.has(parentComponentId)\n ) {\n const prevProps = alternate.memoizedProps;\n const nextProps = fiber.memoizedProps;\n const propsChanged = prevProps !== nextProps;\n\n if (propsChanged) {\n const propChanges = this.diffProps(prevProps, nextProps);\n\n return {\n type: RenderCauseType.PROPS_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n propChanges,\n };\n }\n\n return {\n type: RenderCauseType.PARENT_RENDER,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n };\n }\n\n // State change\n if (fiber.memoizedState !== alternate.memoizedState) {\n return {\n type: RenderCauseType.STATE_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n };\n }\n\n if (fiber.memoizedProps !== alternate.memoizedProps) {\n return {\n type: RenderCauseType.CONTEXT_CHANGE,\n confidence: RenderConfidence.LOW,\n };\n }\n\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.UNKNOWN,\n };\n }\n\n /**\n * Diff props to find which keys changed and whether it's reference-only.\n * This is the key insight generator.\n */\n private diffProps(\n prevProps: Record<string, any> | null,\n nextProps: Record<string, any> | null\n ): PropChangeDetail[] {\n if (!prevProps || !nextProps) {\n return [];\n }\n\n const changes: PropChangeDetail[] = [];\n const allKeys = new Set([\n ...Object.keys(prevProps),\n ...Object.keys(nextProps),\n ]);\n\n const skipKeys = new Set([\"children\", \"key\", \"ref\"]);\n\n for (const key of allKeys) {\n if (skipKeys.has(key)) continue;\n\n const prevValue = prevProps[key];\n const nextValue = nextProps[key];\n\n if (prevValue === nextValue) {\n continue;\n }\n\n const referenceOnly = this.isShallowEqual(prevValue, nextValue);\n\n changes.push({ key, referenceOnly });\n\n if (changes.length >= 10) {\n break;\n }\n }\n\n return changes;\n }\n\n /**\n * Shallow equality check to determine if a prop is reference-only change.\n * We only go one level deep to keep it fast.\n */\n private isShallowEqual(a: any, b: any): boolean {\n // Same reference (already checked, but for safety)\n if (a === b) return true;\n\n // Different types\n if (typeof a !== typeof b) return false;\n\n // Null checks\n if (a === null || b === null) return false;\n\n // Functions - can't easily compare, assume different\n // But if they're both functions, it's likely a reference-only change\n // (same callback recreated)\n if (typeof a === \"function\" && typeof b === \"function\") {\n // We can't compare function bodies easily, but this is almost always\n // a reference-only change (inline callback recreated)\n return true; // Treat as reference-only\n }\n\n // Arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n return true;\n }\n\n return a === b;\n }\n\n private isUserComponent(fiber: MinimalFiber): boolean {\n const tag = fiber.tag;\n return (\n tag === FiberTag.FunctionComponent ||\n tag === FiberTag.ClassComponent ||\n tag === FiberTag.ForwardRef ||\n tag === FiberTag.MemoComponent ||\n tag === FiberTag.SimpleMemoComponent\n );\n }\n\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n private getOrCreateComponentId(fiber: MinimalFiber): string {\n let id = this.fiberToComponentId.get(fiber);\n if (id) return id;\n\n if (fiber.alternate) {\n id = this.fiberToComponentId.get(fiber.alternate);\n if (id) {\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n }\n\n id = `c_${++this.componentIdCounter}`;\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n\n private getComponentName(fiber: MinimalFiber): string {\n const type = fiber.type;\n if (!type) return \"Unknown\";\n\n if (typeof type === \"function\") {\n return type.displayName || type.name || \"Anonymous\";\n }\n\n if (typeof type === \"object\" && type !== null) {\n if (type.displayName) return type.displayName;\n if (type.render)\n return type.render.displayName || type.render.name || \"ForwardRef\";\n if (type.type) {\n const inner = type.type;\n return inner.displayName || inner.name || \"Memo\";\n }\n }\n\n return \"Unknown\";\n }\n\n private getComponentType(fiber: MinimalFiber): ComponentType {\n switch (fiber.tag) {\n case FiberTag.FunctionComponent:\n return \"function\";\n case FiberTag.ClassComponent:\n return \"class\";\n case FiberTag.ForwardRef:\n return \"forwardRef\";\n case FiberTag.MemoComponent:\n case FiberTag.SimpleMemoComponent:\n return \"memo\";\n default:\n return \"unknown\";\n }\n }\n\n /**\n * Force emit current state (useful for debugging or on-demand refresh).\n */\n forceEmit(): void {\n this.emitSnapshot();\n }\n\n /**\n * Get current profile for a component (useful for debugging).\n */\n getProfile(componentId: string): ComponentProfile | undefined {\n return this.profiles.get(componentId);\n }\n\n /**\n * Get all suspicious components.\n */\n getSuspiciousComponents(): ComponentProfile[] {\n return Array.from(this.profiles.values()).filter((p) => p.isSuspicious);\n }\n\n cleanup(): void {\n if (!this.isSetup) return;\n\n this.emitSnapshot();\n\n if (this.snapshotTimer) {\n clearInterval(this.snapshotTimer);\n this.snapshotTimer = null;\n }\n\n if (this.originalHook) {\n if (this.originalOnCommitFiberRoot) {\n this.originalHook.onCommitFiberRoot = this.originalOnCommitFiberRoot;\n }\n if (this.originalOnCommitFiberUnmount) {\n this.originalHook.onCommitFiberUnmount =\n this.originalOnCommitFiberUnmount;\n }\n }\n\n this.originalHook = null;\n this.originalOnCommitFiberRoot = null;\n this.originalOnCommitFiberUnmount = null;\n this.profiles.clear();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n this.config = null;\n this.isSetup = false;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { SDK_VERSION } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.renderInterceptor = new RenderInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, console, and render interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: \"wss://api.getlimelight.io/limelight\",\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n enableRenderInspector: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n\n if (this.config.enableRenderInspector) {\n this.renderInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
package/dist/index.mjs CHANGED
@@ -219,9 +219,7 @@ var SENSITIVE_HEADERS = [
219
219
  "x-secret",
220
220
  "bearer"
221
221
  ];
222
- var DEFAULT_PORT = 9090;
223
- var WS_PATH = "/limelight";
224
- var SDK_VERSION = true ? "0.2.0" : "test-version";
222
+ var SDK_VERSION = true ? "0.2.1" : "test-version";
225
223
  var RENDER_THRESHOLDS = {
226
224
  HOT_VELOCITY: 5,
227
225
  HIGH_RENDER_COUNT: 50,
@@ -1602,7 +1600,7 @@ var LimelightClient = class {
1602
1600
  const isEnabled = config.enabled ?? isDevelopment();
1603
1601
  this.config = {
1604
1602
  appName: "Limelight App",
1605
- serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,
1603
+ serverUrl: "wss://api.getlimelight.io/limelight",
1606
1604
  enabled: isEnabled,
1607
1605
  enableNetworkInspector: true,
1608
1606
  enableConsole: true,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n\n/**\n * Thresholds for suspicious render detection.\n */\nexport const RENDER_THRESHOLDS = {\n HOT_VELOCITY: 5,\n HIGH_RENDER_COUNT: 50,\n VELOCITY_WINDOW_MS: 2000,\n SNAPSHOT_INTERVAL_MS: 1000,\n MIN_DELTA_TO_EMIT: 1,\n MAX_PROP_KEYS_TO_TRACK: 20, // Don't track more than this many unique props\n MAX_PROP_CHANGES_PER_SNAPSHOT: 10, // Limit delta array size\n TOP_PROPS_TO_REPORT: 5, // Only report top N changed props\n} as const;\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","let counter = 0;\n\n/**\n * Generates a unique ID using timestamp + counter + random.\n * Handles high-frequency calls without collision.\n *\n * Format: `{base36-timestamp}{counter}-{random}`\n * Example: `lq2x5k0-a7b3`\n */\nexport const generateRenderId = (): string => {\n const timestamp = Date.now().toString(36);\n const count = (counter++).toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n\n // Reset counter periodically to keep IDs shorter\n if (counter > 1000) counter = 0;\n\n return `${timestamp}${count}-${random}`;\n};\n","import { RenderCauseType } from \"@/types/render\";\n\n/**\n * Creates an empty cause breakdown object with all render cause types initialized to zero.\n * @returns {Record<RenderCauseType, number>} An object with render cause types as keys and zero as values.\n */\nexport const createEmptyCauseBreakdown = (): Record<\n RenderCauseType,\n number\n> => {\n return {\n [RenderCauseType.STATE_CHANGE]: 0,\n [RenderCauseType.PROPS_CHANGE]: 0,\n [RenderCauseType.CONTEXT_CHANGE]: 0,\n [RenderCauseType.PARENT_RENDER]: 0,\n [RenderCauseType.FORCE_UPDATE]: 0,\n [RenderCauseType.UNKNOWN]: 0,\n };\n};\n","import { PropChangeStats } from \"@/types/render\";\n\n/**\n * Creates and returns an empty PropChangeStats object.\n * @returns {PropChangeStats} An object with initialized changeCount and referenceOnlyCount maps.\n */\nexport const createEmptyPropChangeStats = (): PropChangeStats => {\n return {\n changeCount: new Map(),\n referenceOnlyCount: new Map(),\n };\n};\n","// Global accessor for render interceptor (avoids hook requirements)\nlet globalGetTransactionId: (() => string | null) | null = null;\n\n/**\n * Gets the current transaction ID from anywhere (for render interceptor use).\n * Returns null if no provider is mounted or no transaction is active.\n * @return {string | null} The current transaction ID or null.\n */\nexport const getCurrentTransactionId = (): string | null => {\n return globalGetTransactionId?.() ?? null;\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n let responseData;\n\n const responseType = this.responseType || \"\";\n\n if (responseType === \"\" || responseType === \"text\") {\n responseData = this.responseText;\n } else if (\n responseType === \"blob\" ||\n responseType === \"arraybuffer\"\n ) {\n responseData = `[Binary Data: ${responseType}]`;\n } else if (responseType === \"json\") {\n responseData = this.response;\n } else {\n responseData = this.response;\n }\n\n const responseBody = serializeBody(\n responseData,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import {\n RenderPhase,\n RenderCauseType,\n RenderConfidence,\n ComponentType,\n MinimalFiber,\n ReactDevToolsHook,\n FiberTag,\n FiberFlags,\n ComponentProfile,\n PropChangeDetail,\n PropChangeSnapshot,\n ComponentProfileSnapshot,\n} from \"@/types/render\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n createEmptyPropChangeStats,\n generateRenderId,\n getCurrentTransactionId,\n isDevelopment,\n} from \"@/helpers\";\nimport { createEmptyCauseBreakdown } from \"@/helpers/render/createEmptyCauseBreakdown\";\nimport { RENDER_THRESHOLDS } from \"@/constants\";\n\n/**\n * Intercepts React renders via the DevTools global hook.\n */\nexport class RenderInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n private profiles = new Map<string, ComponentProfile>();\n private fiberToComponentId = new WeakMap<MinimalFiber, string>();\n private componentIdCounter = 0;\n\n private snapshotTimer: ReturnType<typeof setInterval> | null = null;\n\n private currentCommitComponents = new Set<string>();\n private componentsInCurrentCommit = 0;\n\n private originalHook: ReactDevToolsHook | null = null;\n\n private originalOnCommitFiberRoot:\n | ReactDevToolsHook[\"onCommitFiberRoot\"]\n | null = null;\n private originalOnCommitFiberUnmount:\n | ReactDevToolsHook[\"onCommitFiberUnmount\"]\n | null = null;\n\n private pendingUnmounts: ComponentProfile[] = [];\n\n constructor(\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string\n ) {\n this.sendMessage = sendMessage;\n this.getSessionId = getSessionId;\n }\n\n setup(config: LimelightConfig): void {\n if (this.isSetup) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n console.warn(\"[Limelight] Failed to install render hook\");\n return;\n }\n\n this.snapshotTimer = setInterval(() => {\n this.emitSnapshot();\n }, RENDER_THRESHOLDS.SNAPSHOT_INTERVAL_MS);\n\n this.isSetup = true;\n }\n\n private installHook(): boolean {\n const globalObj =\n typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : null;\n\n if (!globalObj) return false;\n\n const hookKey = \"__REACT_DEVTOOLS_GLOBAL_HOOK__\";\n const existingHook = (globalObj as any)[hookKey] as\n | ReactDevToolsHook\n | undefined;\n\n if (existingHook) {\n this.wrapExistingHook(existingHook);\n } else {\n this.createHook(globalObj, hookKey);\n }\n\n return true;\n }\n\n private wrapExistingHook(hook: ReactDevToolsHook): void {\n this.originalHook = hook;\n this.originalOnCommitFiberRoot = hook.onCommitFiberRoot?.bind(hook);\n this.originalOnCommitFiberUnmount = hook.onCommitFiberUnmount?.bind(hook);\n\n hook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {\n this.originalOnCommitFiberRoot?.(rendererID, root, priorityLevel);\n this.handleCommitFiberRoot(rendererID, root);\n };\n\n hook.onCommitFiberUnmount = (rendererID, fiber) => {\n this.originalOnCommitFiberUnmount?.(rendererID, fiber);\n this.handleCommitFiberUnmount(rendererID, fiber);\n };\n }\n\n private createHook(globalObj: any, hookKey: string): void {\n const renderers = new Map<number, any>();\n let rendererIdCounter = 0;\n\n const hook: ReactDevToolsHook = {\n supportsFiber: true,\n inject: (renderer) => {\n const id = ++rendererIdCounter;\n renderers.set(id, renderer);\n return id;\n },\n onCommitFiberRoot: (rendererID, root, priorityLevel) => {\n this.handleCommitFiberRoot(rendererID, root);\n },\n onCommitFiberUnmount: (rendererID, fiber) => {\n this.handleCommitFiberUnmount(rendererID, fiber);\n },\n };\n\n globalObj[hookKey] = hook;\n }\n /**\n * Handles a fiber root commit - walks tree and ACCUMULATES into profiles.\n * Two-pass: first count components, then accumulate with distributed cost.\n */\n private handleCommitFiberRoot(\n _rendererID: number,\n root: { current: MinimalFiber }\n ): void {\n this.currentCommitComponents.clear();\n this.componentsInCurrentCommit = 0;\n\n try {\n this.countRenderedComponents(root.current);\n this.walkFiberTree(root.current, null, 0);\n } catch (error) {\n if (isDevelopment()) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n */\n private countRenderedComponents(fiber: MinimalFiber | null): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n this.componentsInCurrentCommit++;\n }\n\n this.countRenderedComponents(fiber.child);\n this.countRenderedComponents(fiber.sibling);\n }\n\n private handleCommitFiberUnmount(\n _rendererID: number,\n fiber: MinimalFiber\n ): void {\n if (!this.isUserComponent(fiber)) return;\n\n const componentId = this.fiberToComponentId.get(fiber);\n if (!componentId) return;\n\n const profile = this.profiles.get(componentId);\n if (profile) {\n profile.unmountedAt = Date.now();\n this.pendingUnmounts.push(profile);\n this.profiles.delete(componentId);\n }\n }\n\n /**\n * Walks fiber tree and accumulates render stats into profiles.\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number\n ): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n const componentId = this.getOrCreateComponentId(fiber);\n this.accumulateRender(fiber, componentId, parentComponentId, depth);\n this.currentCommitComponents.add(componentId);\n parentComponentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, parentComponentId, depth + 1);\n this.walkFiberTree(fiber.sibling, parentComponentId, depth);\n }\n\n /**\n * Core accumulation logic - this is where we build up the profile.\n */\n private accumulateRender(\n fiber: MinimalFiber,\n componentId: string,\n parentComponentId: string | null,\n depth: number\n ): void {\n const now = Date.now();\n const cause = this.inferRenderCause(fiber, parentComponentId);\n\n const renderCost =\n this.componentsInCurrentCommit > 0\n ? 1 / this.componentsInCurrentCommit\n : 1;\n\n let profile = this.profiles.get(componentId);\n\n if (!profile) {\n profile = {\n id: generateRenderId(),\n componentId,\n componentName: this.getComponentName(fiber),\n componentType: this.getComponentType(fiber),\n mountedAt: now,\n totalRenders: 0,\n totalRenderCost: 0,\n velocityWindowStart: now,\n velocityWindowCount: 0,\n causeBreakdown: createEmptyCauseBreakdown(),\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n lastEmittedRenderCount: 0,\n lastEmittedRenderCost: 0,\n lastEmitTime: now,\n parentCounts: new Map(),\n depth,\n isSuspicious: false,\n // NEW\n propChangeStats: createEmptyPropChangeStats(),\n propChangeDelta: [],\n };\n this.profiles.set(componentId, profile);\n }\n\n profile.totalRenders++;\n profile.totalRenderCost += renderCost;\n\n profile.causeBreakdown[cause.type]++;\n profile.causeDeltaBreakdown[cause.type]++;\n\n if (cause.type === RenderCauseType.PROPS_CHANGE && cause.propChanges) {\n this.accumulatePropChanges(profile, cause.propChanges);\n }\n\n const transactionId = getCurrentTransactionId();\n\n if (transactionId) {\n profile.lastTransactionId = transactionId;\n }\n\n if (parentComponentId) {\n const count = (profile.parentCounts.get(parentComponentId) ?? 0) + 1;\n profile.parentCounts.set(parentComponentId, count);\n\n if (\n !profile.primaryParentId ||\n count > (profile.parentCounts.get(profile.primaryParentId) ?? 0)\n ) {\n profile.primaryParentId = parentComponentId;\n }\n }\n\n profile.depth = depth;\n\n const windowStart = now - RENDER_THRESHOLDS.VELOCITY_WINDOW_MS;\n if (profile.velocityWindowStart < windowStart) {\n profile.velocityWindowStart = now;\n profile.velocityWindowCount = 1;\n } else {\n profile.velocityWindowCount++;\n }\n\n this.updateSuspiciousFlag(profile);\n }\n\n /**\n * NEW: Accumulate prop change details into the profile.\n */\n private accumulatePropChanges(\n profile: ComponentProfile,\n changes: PropChangeDetail[]\n ): void {\n const stats = profile.propChangeStats;\n\n for (const change of changes) {\n if (\n stats.changeCount.size >= RENDER_THRESHOLDS.MAX_PROP_KEYS_TO_TRACK &&\n !stats.changeCount.has(change.key)\n ) {\n continue;\n }\n\n stats.changeCount.set(\n change.key,\n (stats.changeCount.get(change.key) ?? 0) + 1\n );\n\n if (change.referenceOnly) {\n stats.referenceOnlyCount.set(\n change.key,\n (stats.referenceOnlyCount.get(change.key) ?? 0) + 1\n );\n }\n }\n\n if (\n profile.propChangeDelta.length <\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT\n ) {\n profile.propChangeDelta.push(\n ...changes.slice(\n 0,\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT -\n profile.propChangeDelta.length\n )\n );\n }\n }\n\n /**\n * Build prop change snapshot for emission.\n */\n private buildPropChangeSnapshot(\n profile: ComponentProfile\n ): PropChangeSnapshot | undefined {\n const stats = profile.propChangeStats;\n\n if (stats.changeCount.size === 0) {\n return undefined;\n }\n\n const sorted = Array.from(stats.changeCount.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, RENDER_THRESHOLDS.TOP_PROPS_TO_REPORT);\n\n const topChangedProps = sorted.map(([key, count]) => {\n const refOnlyCount = stats.referenceOnlyCount.get(key) ?? 0;\n return {\n key,\n count,\n referenceOnlyPercent:\n count > 0 ? Math.round((refOnlyCount / count) * 100) : 0,\n };\n });\n\n return { topChangedProps };\n }\n\n private updateSuspiciousFlag(profile: ComponentProfile): void {\n const velocity = this.calculateVelocity(profile);\n\n if (velocity > RENDER_THRESHOLDS.HOT_VELOCITY) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High render velocity: ${velocity.toFixed(\n 1\n )}/sec`;\n } else if (profile.totalRenders > RENDER_THRESHOLDS.HIGH_RENDER_COUNT) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High total renders: ${profile.totalRenders}`;\n } else {\n profile.isSuspicious = false;\n profile.suspiciousReason = undefined;\n }\n }\n\n /**\n * Calculates renders per second from velocity window.\n * Cheap: just count / window duration, no array operations.\n */\n private calculateVelocity(profile: ComponentProfile): number {\n const now = Date.now();\n const windowAge = now - profile.velocityWindowStart;\n\n if (windowAge > RENDER_THRESHOLDS.VELOCITY_WINDOW_MS) {\n return 0;\n }\n\n const effectiveWindowMs = Math.max(windowAge, 100);\n return (profile.velocityWindowCount / effectiveWindowMs) * 1000;\n }\n\n /**\n * Emits a snapshot of all profiles with deltas.\n */\n private emitSnapshot(): void {\n const now = Date.now();\n const snapshots: ComponentProfileSnapshot[] = [];\n\n for (const profile of this.profiles.values()) {\n const rendersDelta =\n profile.totalRenders - profile.lastEmittedRenderCount;\n\n if (\n rendersDelta < RENDER_THRESHOLDS.MIN_DELTA_TO_EMIT &&\n !profile.isSuspicious\n ) {\n continue;\n }\n\n const velocity = this.calculateVelocity(profile);\n const isMount = profile.lastEmittedRenderCount === 0;\n const renderCostDelta =\n profile.totalRenderCost - profile.lastEmittedRenderCost;\n\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost: profile.totalRenderCost / profile.totalRenders,\n rendersDelta,\n renderCostDelta,\n renderVelocity: velocity,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: { ...profile.causeDeltaBreakdown },\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: isMount ? RenderPhase.MOUNT : RenderPhase.UPDATE,\n mountedAt: profile.mountedAt,\n propChanges,\n });\n\n profile.lastEmittedRenderCount = profile.totalRenders;\n profile.lastEmittedRenderCost = profile.totalRenderCost;\n profile.lastEmitTime = now;\n profile.causeDeltaBreakdown = createEmptyCauseBreakdown();\n profile.propChangeDelta = [];\n }\n\n for (const profile of this.pendingUnmounts) {\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost:\n profile.totalRenderCost / Math.max(profile.totalRenders, 1),\n rendersDelta: 0,\n renderCostDelta: 0,\n renderVelocity: 0,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: RenderPhase.UNMOUNT,\n mountedAt: profile.mountedAt,\n unmountedAt: profile.unmountedAt,\n propChanges,\n });\n }\n this.pendingUnmounts = [];\n\n if (snapshots.length === 0) return;\n\n let message: LimelightMessage = {\n phase: \"RENDER_SNAPSHOT\",\n sessionId: this.getSessionId(),\n timestamp: now,\n profiles: snapshots,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(message);\n if (!modified) return;\n message = modified;\n }\n\n this.sendMessage(message);\n }\n\n /**\n * Now returns prop change details when applicable.\n */\n private inferRenderCause(\n fiber: MinimalFiber,\n parentComponentId: string | null\n ): {\n type: RenderCauseType;\n confidence: RenderConfidence;\n triggerId?: string;\n propChanges?: PropChangeDetail[]; // NEW\n } {\n const alternate = fiber.alternate;\n\n if (!alternate) {\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.HIGH,\n };\n }\n\n if (\n parentComponentId &&\n this.currentCommitComponents.has(parentComponentId)\n ) {\n const prevProps = alternate.memoizedProps;\n const nextProps = fiber.memoizedProps;\n const propsChanged = prevProps !== nextProps;\n\n if (propsChanged) {\n const propChanges = this.diffProps(prevProps, nextProps);\n\n return {\n type: RenderCauseType.PROPS_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n propChanges,\n };\n }\n\n return {\n type: RenderCauseType.PARENT_RENDER,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n };\n }\n\n // State change\n if (fiber.memoizedState !== alternate.memoizedState) {\n return {\n type: RenderCauseType.STATE_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n };\n }\n\n if (fiber.memoizedProps !== alternate.memoizedProps) {\n return {\n type: RenderCauseType.CONTEXT_CHANGE,\n confidence: RenderConfidence.LOW,\n };\n }\n\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.UNKNOWN,\n };\n }\n\n /**\n * Diff props to find which keys changed and whether it's reference-only.\n * This is the key insight generator.\n */\n private diffProps(\n prevProps: Record<string, any> | null,\n nextProps: Record<string, any> | null\n ): PropChangeDetail[] {\n if (!prevProps || !nextProps) {\n return [];\n }\n\n const changes: PropChangeDetail[] = [];\n const allKeys = new Set([\n ...Object.keys(prevProps),\n ...Object.keys(nextProps),\n ]);\n\n const skipKeys = new Set([\"children\", \"key\", \"ref\"]);\n\n for (const key of allKeys) {\n if (skipKeys.has(key)) continue;\n\n const prevValue = prevProps[key];\n const nextValue = nextProps[key];\n\n if (prevValue === nextValue) {\n continue;\n }\n\n const referenceOnly = this.isShallowEqual(prevValue, nextValue);\n\n changes.push({ key, referenceOnly });\n\n if (changes.length >= 10) {\n break;\n }\n }\n\n return changes;\n }\n\n /**\n * Shallow equality check to determine if a prop is reference-only change.\n * We only go one level deep to keep it fast.\n */\n private isShallowEqual(a: any, b: any): boolean {\n // Same reference (already checked, but for safety)\n if (a === b) return true;\n\n // Different types\n if (typeof a !== typeof b) return false;\n\n // Null checks\n if (a === null || b === null) return false;\n\n // Functions - can't easily compare, assume different\n // But if they're both functions, it's likely a reference-only change\n // (same callback recreated)\n if (typeof a === \"function\" && typeof b === \"function\") {\n // We can't compare function bodies easily, but this is almost always\n // a reference-only change (inline callback recreated)\n return true; // Treat as reference-only\n }\n\n // Arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n return true;\n }\n\n return a === b;\n }\n\n private isUserComponent(fiber: MinimalFiber): boolean {\n const tag = fiber.tag;\n return (\n tag === FiberTag.FunctionComponent ||\n tag === FiberTag.ClassComponent ||\n tag === FiberTag.ForwardRef ||\n tag === FiberTag.MemoComponent ||\n tag === FiberTag.SimpleMemoComponent\n );\n }\n\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n private getOrCreateComponentId(fiber: MinimalFiber): string {\n let id = this.fiberToComponentId.get(fiber);\n if (id) return id;\n\n if (fiber.alternate) {\n id = this.fiberToComponentId.get(fiber.alternate);\n if (id) {\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n }\n\n id = `c_${++this.componentIdCounter}`;\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n\n private getComponentName(fiber: MinimalFiber): string {\n const type = fiber.type;\n if (!type) return \"Unknown\";\n\n if (typeof type === \"function\") {\n return type.displayName || type.name || \"Anonymous\";\n }\n\n if (typeof type === \"object\" && type !== null) {\n if (type.displayName) return type.displayName;\n if (type.render)\n return type.render.displayName || type.render.name || \"ForwardRef\";\n if (type.type) {\n const inner = type.type;\n return inner.displayName || inner.name || \"Memo\";\n }\n }\n\n return \"Unknown\";\n }\n\n private getComponentType(fiber: MinimalFiber): ComponentType {\n switch (fiber.tag) {\n case FiberTag.FunctionComponent:\n return \"function\";\n case FiberTag.ClassComponent:\n return \"class\";\n case FiberTag.ForwardRef:\n return \"forwardRef\";\n case FiberTag.MemoComponent:\n case FiberTag.SimpleMemoComponent:\n return \"memo\";\n default:\n return \"unknown\";\n }\n }\n\n /**\n * Force emit current state (useful for debugging or on-demand refresh).\n */\n forceEmit(): void {\n this.emitSnapshot();\n }\n\n /**\n * Get current profile for a component (useful for debugging).\n */\n getProfile(componentId: string): ComponentProfile | undefined {\n return this.profiles.get(componentId);\n }\n\n /**\n * Get all suspicious components.\n */\n getSuspiciousComponents(): ComponentProfile[] {\n return Array.from(this.profiles.values()).filter((p) => p.isSuspicious);\n }\n\n cleanup(): void {\n if (!this.isSetup) return;\n\n this.emitSnapshot();\n\n if (this.snapshotTimer) {\n clearInterval(this.snapshotTimer);\n this.snapshotTimer = null;\n }\n\n if (this.originalHook) {\n if (this.originalOnCommitFiberRoot) {\n this.originalHook.onCommitFiberRoot = this.originalOnCommitFiberRoot;\n }\n if (this.originalOnCommitFiberUnmount) {\n this.originalHook.onCommitFiberUnmount =\n this.originalOnCommitFiberUnmount;\n }\n }\n\n this.originalHook = null;\n this.originalOnCommitFiberRoot = null;\n this.originalOnCommitFiberUnmount = null;\n this.profiles.clear();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n this.config = null;\n this.isSetup = false;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, SDK_VERSION, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.renderInterceptor = new RenderInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, console, and render interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n enableRenderInspector: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n\n if (this.config.enableRenderInspector) {\n this.renderInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
1
+ {"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n\n/**\n * Thresholds for suspicious render detection.\n */\nexport const RENDER_THRESHOLDS = {\n HOT_VELOCITY: 5,\n HIGH_RENDER_COUNT: 50,\n VELOCITY_WINDOW_MS: 2000,\n SNAPSHOT_INTERVAL_MS: 1000,\n MIN_DELTA_TO_EMIT: 1,\n MAX_PROP_KEYS_TO_TRACK: 20, // Don't track more than this many unique props\n MAX_PROP_CHANGES_PER_SNAPSHOT: 10, // Limit delta array size\n TOP_PROPS_TO_REPORT: 5, // Only report top N changed props\n} as const;\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","let counter = 0;\n\n/**\n * Generates a unique ID using timestamp + counter + random.\n * Handles high-frequency calls without collision.\n *\n * Format: `{base36-timestamp}{counter}-{random}`\n * Example: `lq2x5k0-a7b3`\n */\nexport const generateRenderId = (): string => {\n const timestamp = Date.now().toString(36);\n const count = (counter++).toString(36);\n const random = Math.random().toString(36).substring(2, 6);\n\n // Reset counter periodically to keep IDs shorter\n if (counter > 1000) counter = 0;\n\n return `${timestamp}${count}-${random}`;\n};\n","import { RenderCauseType } from \"@/types/render\";\n\n/**\n * Creates an empty cause breakdown object with all render cause types initialized to zero.\n * @returns {Record<RenderCauseType, number>} An object with render cause types as keys and zero as values.\n */\nexport const createEmptyCauseBreakdown = (): Record<\n RenderCauseType,\n number\n> => {\n return {\n [RenderCauseType.STATE_CHANGE]: 0,\n [RenderCauseType.PROPS_CHANGE]: 0,\n [RenderCauseType.CONTEXT_CHANGE]: 0,\n [RenderCauseType.PARENT_RENDER]: 0,\n [RenderCauseType.FORCE_UPDATE]: 0,\n [RenderCauseType.UNKNOWN]: 0,\n };\n};\n","import { PropChangeStats } from \"@/types/render\";\n\n/**\n * Creates and returns an empty PropChangeStats object.\n * @returns {PropChangeStats} An object with initialized changeCount and referenceOnlyCount maps.\n */\nexport const createEmptyPropChangeStats = (): PropChangeStats => {\n return {\n changeCount: new Map(),\n referenceOnlyCount: new Map(),\n };\n};\n","// Global accessor for render interceptor (avoids hook requirements)\nlet globalGetTransactionId: (() => string | null) | null = null;\n\n/**\n * Gets the current transaction ID from anywhere (for render interceptor use).\n * Returns null if no provider is mounted or no transaction is active.\n * @return {string | null} The current transaction ID or null.\n */\nexport const getCurrentTransactionId = (): string | null => {\n return globalGetTransactionId?.() ?? null;\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n let responseData;\n\n const responseType = this.responseType || \"\";\n\n if (responseType === \"\" || responseType === \"text\") {\n responseData = this.responseText;\n } else if (\n responseType === \"blob\" ||\n responseType === \"arraybuffer\"\n ) {\n responseData = `[Binary Data: ${responseType}]`;\n } else if (responseType === \"json\") {\n responseData = this.response;\n } else {\n responseData = this.response;\n }\n\n const responseBody = serializeBody(\n responseData,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import {\n RenderPhase,\n RenderCauseType,\n RenderConfidence,\n ComponentType,\n MinimalFiber,\n ReactDevToolsHook,\n FiberTag,\n FiberFlags,\n ComponentProfile,\n PropChangeDetail,\n PropChangeSnapshot,\n ComponentProfileSnapshot,\n} from \"@/types/render\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n createEmptyPropChangeStats,\n generateRenderId,\n getCurrentTransactionId,\n isDevelopment,\n} from \"@/helpers\";\nimport { createEmptyCauseBreakdown } from \"@/helpers/render/createEmptyCauseBreakdown\";\nimport { RENDER_THRESHOLDS } from \"@/constants\";\n\n/**\n * Intercepts React renders via the DevTools global hook.\n */\nexport class RenderInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n private profiles = new Map<string, ComponentProfile>();\n private fiberToComponentId = new WeakMap<MinimalFiber, string>();\n private componentIdCounter = 0;\n\n private snapshotTimer: ReturnType<typeof setInterval> | null = null;\n\n private currentCommitComponents = new Set<string>();\n private componentsInCurrentCommit = 0;\n\n private originalHook: ReactDevToolsHook | null = null;\n\n private originalOnCommitFiberRoot:\n | ReactDevToolsHook[\"onCommitFiberRoot\"]\n | null = null;\n private originalOnCommitFiberUnmount:\n | ReactDevToolsHook[\"onCommitFiberUnmount\"]\n | null = null;\n\n private pendingUnmounts: ComponentProfile[] = [];\n\n constructor(\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string\n ) {\n this.sendMessage = sendMessage;\n this.getSessionId = getSessionId;\n }\n\n setup(config: LimelightConfig): void {\n if (this.isSetup) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n console.warn(\"[Limelight] Failed to install render hook\");\n return;\n }\n\n this.snapshotTimer = setInterval(() => {\n this.emitSnapshot();\n }, RENDER_THRESHOLDS.SNAPSHOT_INTERVAL_MS);\n\n this.isSetup = true;\n }\n\n private installHook(): boolean {\n const globalObj =\n typeof window !== \"undefined\"\n ? window\n : typeof global !== \"undefined\"\n ? global\n : null;\n\n if (!globalObj) return false;\n\n const hookKey = \"__REACT_DEVTOOLS_GLOBAL_HOOK__\";\n const existingHook = (globalObj as any)[hookKey] as\n | ReactDevToolsHook\n | undefined;\n\n if (existingHook) {\n this.wrapExistingHook(existingHook);\n } else {\n this.createHook(globalObj, hookKey);\n }\n\n return true;\n }\n\n private wrapExistingHook(hook: ReactDevToolsHook): void {\n this.originalHook = hook;\n this.originalOnCommitFiberRoot = hook.onCommitFiberRoot?.bind(hook);\n this.originalOnCommitFiberUnmount = hook.onCommitFiberUnmount?.bind(hook);\n\n hook.onCommitFiberRoot = (rendererID, root, priorityLevel) => {\n this.originalOnCommitFiberRoot?.(rendererID, root, priorityLevel);\n this.handleCommitFiberRoot(rendererID, root);\n };\n\n hook.onCommitFiberUnmount = (rendererID, fiber) => {\n this.originalOnCommitFiberUnmount?.(rendererID, fiber);\n this.handleCommitFiberUnmount(rendererID, fiber);\n };\n }\n\n private createHook(globalObj: any, hookKey: string): void {\n const renderers = new Map<number, any>();\n let rendererIdCounter = 0;\n\n const hook: ReactDevToolsHook = {\n supportsFiber: true,\n inject: (renderer) => {\n const id = ++rendererIdCounter;\n renderers.set(id, renderer);\n return id;\n },\n onCommitFiberRoot: (rendererID, root, priorityLevel) => {\n this.handleCommitFiberRoot(rendererID, root);\n },\n onCommitFiberUnmount: (rendererID, fiber) => {\n this.handleCommitFiberUnmount(rendererID, fiber);\n },\n };\n\n globalObj[hookKey] = hook;\n }\n /**\n * Handles a fiber root commit - walks tree and ACCUMULATES into profiles.\n * Two-pass: first count components, then accumulate with distributed cost.\n */\n private handleCommitFiberRoot(\n _rendererID: number,\n root: { current: MinimalFiber }\n ): void {\n this.currentCommitComponents.clear();\n this.componentsInCurrentCommit = 0;\n\n try {\n this.countRenderedComponents(root.current);\n this.walkFiberTree(root.current, null, 0);\n } catch (error) {\n if (isDevelopment()) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n */\n private countRenderedComponents(fiber: MinimalFiber | null): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n this.componentsInCurrentCommit++;\n }\n\n this.countRenderedComponents(fiber.child);\n this.countRenderedComponents(fiber.sibling);\n }\n\n private handleCommitFiberUnmount(\n _rendererID: number,\n fiber: MinimalFiber\n ): void {\n if (!this.isUserComponent(fiber)) return;\n\n const componentId = this.fiberToComponentId.get(fiber);\n if (!componentId) return;\n\n const profile = this.profiles.get(componentId);\n if (profile) {\n profile.unmountedAt = Date.now();\n this.pendingUnmounts.push(profile);\n this.profiles.delete(componentId);\n }\n }\n\n /**\n * Walks fiber tree and accumulates render stats into profiles.\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number\n ): void {\n if (!fiber) return;\n\n if (this.isUserComponent(fiber) && this.didFiberRender(fiber)) {\n const componentId = this.getOrCreateComponentId(fiber);\n this.accumulateRender(fiber, componentId, parentComponentId, depth);\n this.currentCommitComponents.add(componentId);\n parentComponentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, parentComponentId, depth + 1);\n this.walkFiberTree(fiber.sibling, parentComponentId, depth);\n }\n\n /**\n * Core accumulation logic - this is where we build up the profile.\n */\n private accumulateRender(\n fiber: MinimalFiber,\n componentId: string,\n parentComponentId: string | null,\n depth: number\n ): void {\n const now = Date.now();\n const cause = this.inferRenderCause(fiber, parentComponentId);\n\n const renderCost =\n this.componentsInCurrentCommit > 0\n ? 1 / this.componentsInCurrentCommit\n : 1;\n\n let profile = this.profiles.get(componentId);\n\n if (!profile) {\n profile = {\n id: generateRenderId(),\n componentId,\n componentName: this.getComponentName(fiber),\n componentType: this.getComponentType(fiber),\n mountedAt: now,\n totalRenders: 0,\n totalRenderCost: 0,\n velocityWindowStart: now,\n velocityWindowCount: 0,\n causeBreakdown: createEmptyCauseBreakdown(),\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n lastEmittedRenderCount: 0,\n lastEmittedRenderCost: 0,\n lastEmitTime: now,\n parentCounts: new Map(),\n depth,\n isSuspicious: false,\n // NEW\n propChangeStats: createEmptyPropChangeStats(),\n propChangeDelta: [],\n };\n this.profiles.set(componentId, profile);\n }\n\n profile.totalRenders++;\n profile.totalRenderCost += renderCost;\n\n profile.causeBreakdown[cause.type]++;\n profile.causeDeltaBreakdown[cause.type]++;\n\n if (cause.type === RenderCauseType.PROPS_CHANGE && cause.propChanges) {\n this.accumulatePropChanges(profile, cause.propChanges);\n }\n\n const transactionId = getCurrentTransactionId();\n\n if (transactionId) {\n profile.lastTransactionId = transactionId;\n }\n\n if (parentComponentId) {\n const count = (profile.parentCounts.get(parentComponentId) ?? 0) + 1;\n profile.parentCounts.set(parentComponentId, count);\n\n if (\n !profile.primaryParentId ||\n count > (profile.parentCounts.get(profile.primaryParentId) ?? 0)\n ) {\n profile.primaryParentId = parentComponentId;\n }\n }\n\n profile.depth = depth;\n\n const windowStart = now - RENDER_THRESHOLDS.VELOCITY_WINDOW_MS;\n if (profile.velocityWindowStart < windowStart) {\n profile.velocityWindowStart = now;\n profile.velocityWindowCount = 1;\n } else {\n profile.velocityWindowCount++;\n }\n\n this.updateSuspiciousFlag(profile);\n }\n\n /**\n * NEW: Accumulate prop change details into the profile.\n */\n private accumulatePropChanges(\n profile: ComponentProfile,\n changes: PropChangeDetail[]\n ): void {\n const stats = profile.propChangeStats;\n\n for (const change of changes) {\n if (\n stats.changeCount.size >= RENDER_THRESHOLDS.MAX_PROP_KEYS_TO_TRACK &&\n !stats.changeCount.has(change.key)\n ) {\n continue;\n }\n\n stats.changeCount.set(\n change.key,\n (stats.changeCount.get(change.key) ?? 0) + 1\n );\n\n if (change.referenceOnly) {\n stats.referenceOnlyCount.set(\n change.key,\n (stats.referenceOnlyCount.get(change.key) ?? 0) + 1\n );\n }\n }\n\n if (\n profile.propChangeDelta.length <\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT\n ) {\n profile.propChangeDelta.push(\n ...changes.slice(\n 0,\n RENDER_THRESHOLDS.MAX_PROP_CHANGES_PER_SNAPSHOT -\n profile.propChangeDelta.length\n )\n );\n }\n }\n\n /**\n * Build prop change snapshot for emission.\n */\n private buildPropChangeSnapshot(\n profile: ComponentProfile\n ): PropChangeSnapshot | undefined {\n const stats = profile.propChangeStats;\n\n if (stats.changeCount.size === 0) {\n return undefined;\n }\n\n const sorted = Array.from(stats.changeCount.entries())\n .sort((a, b) => b[1] - a[1])\n .slice(0, RENDER_THRESHOLDS.TOP_PROPS_TO_REPORT);\n\n const topChangedProps = sorted.map(([key, count]) => {\n const refOnlyCount = stats.referenceOnlyCount.get(key) ?? 0;\n return {\n key,\n count,\n referenceOnlyPercent:\n count > 0 ? Math.round((refOnlyCount / count) * 100) : 0,\n };\n });\n\n return { topChangedProps };\n }\n\n private updateSuspiciousFlag(profile: ComponentProfile): void {\n const velocity = this.calculateVelocity(profile);\n\n if (velocity > RENDER_THRESHOLDS.HOT_VELOCITY) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High render velocity: ${velocity.toFixed(\n 1\n )}/sec`;\n } else if (profile.totalRenders > RENDER_THRESHOLDS.HIGH_RENDER_COUNT) {\n profile.isSuspicious = true;\n profile.suspiciousReason = `High total renders: ${profile.totalRenders}`;\n } else {\n profile.isSuspicious = false;\n profile.suspiciousReason = undefined;\n }\n }\n\n /**\n * Calculates renders per second from velocity window.\n * Cheap: just count / window duration, no array operations.\n */\n private calculateVelocity(profile: ComponentProfile): number {\n const now = Date.now();\n const windowAge = now - profile.velocityWindowStart;\n\n if (windowAge > RENDER_THRESHOLDS.VELOCITY_WINDOW_MS) {\n return 0;\n }\n\n const effectiveWindowMs = Math.max(windowAge, 100);\n return (profile.velocityWindowCount / effectiveWindowMs) * 1000;\n }\n\n /**\n * Emits a snapshot of all profiles with deltas.\n */\n private emitSnapshot(): void {\n const now = Date.now();\n const snapshots: ComponentProfileSnapshot[] = [];\n\n for (const profile of this.profiles.values()) {\n const rendersDelta =\n profile.totalRenders - profile.lastEmittedRenderCount;\n\n if (\n rendersDelta < RENDER_THRESHOLDS.MIN_DELTA_TO_EMIT &&\n !profile.isSuspicious\n ) {\n continue;\n }\n\n const velocity = this.calculateVelocity(profile);\n const isMount = profile.lastEmittedRenderCount === 0;\n const renderCostDelta =\n profile.totalRenderCost - profile.lastEmittedRenderCost;\n\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost: profile.totalRenderCost / profile.totalRenders,\n rendersDelta,\n renderCostDelta,\n renderVelocity: velocity,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: { ...profile.causeDeltaBreakdown },\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: isMount ? RenderPhase.MOUNT : RenderPhase.UPDATE,\n mountedAt: profile.mountedAt,\n propChanges,\n });\n\n profile.lastEmittedRenderCount = profile.totalRenders;\n profile.lastEmittedRenderCost = profile.totalRenderCost;\n profile.lastEmitTime = now;\n profile.causeDeltaBreakdown = createEmptyCauseBreakdown();\n profile.propChangeDelta = [];\n }\n\n for (const profile of this.pendingUnmounts) {\n const propChanges = this.buildPropChangeSnapshot(profile);\n\n snapshots.push({\n id: profile.id,\n componentId: profile.componentId,\n componentName: profile.componentName,\n componentType: profile.componentType,\n totalRenders: profile.totalRenders,\n totalRenderCost: profile.totalRenderCost,\n avgRenderCost:\n profile.totalRenderCost / Math.max(profile.totalRenders, 1),\n rendersDelta: 0,\n renderCostDelta: 0,\n renderVelocity: 0,\n causeBreakdown: { ...profile.causeBreakdown },\n causeDeltaBreakdown: createEmptyCauseBreakdown(),\n parentComponentId: profile.primaryParentId,\n depth: profile.depth,\n lastTransactionId: profile.lastTransactionId,\n isSuspicious: profile.isSuspicious,\n suspiciousReason: profile.suspiciousReason,\n renderPhase: RenderPhase.UNMOUNT,\n mountedAt: profile.mountedAt,\n unmountedAt: profile.unmountedAt,\n propChanges,\n });\n }\n this.pendingUnmounts = [];\n\n if (snapshots.length === 0) return;\n\n let message: LimelightMessage = {\n phase: \"RENDER_SNAPSHOT\",\n sessionId: this.getSessionId(),\n timestamp: now,\n profiles: snapshots,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(message);\n if (!modified) return;\n message = modified;\n }\n\n this.sendMessage(message);\n }\n\n /**\n * Now returns prop change details when applicable.\n */\n private inferRenderCause(\n fiber: MinimalFiber,\n parentComponentId: string | null\n ): {\n type: RenderCauseType;\n confidence: RenderConfidence;\n triggerId?: string;\n propChanges?: PropChangeDetail[]; // NEW\n } {\n const alternate = fiber.alternate;\n\n if (!alternate) {\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.HIGH,\n };\n }\n\n if (\n parentComponentId &&\n this.currentCommitComponents.has(parentComponentId)\n ) {\n const prevProps = alternate.memoizedProps;\n const nextProps = fiber.memoizedProps;\n const propsChanged = prevProps !== nextProps;\n\n if (propsChanged) {\n const propChanges = this.diffProps(prevProps, nextProps);\n\n return {\n type: RenderCauseType.PROPS_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n propChanges,\n };\n }\n\n return {\n type: RenderCauseType.PARENT_RENDER,\n confidence: RenderConfidence.MEDIUM,\n triggerId: parentComponentId,\n };\n }\n\n // State change\n if (fiber.memoizedState !== alternate.memoizedState) {\n return {\n type: RenderCauseType.STATE_CHANGE,\n confidence: RenderConfidence.MEDIUM,\n };\n }\n\n if (fiber.memoizedProps !== alternate.memoizedProps) {\n return {\n type: RenderCauseType.CONTEXT_CHANGE,\n confidence: RenderConfidence.LOW,\n };\n }\n\n return {\n type: RenderCauseType.UNKNOWN,\n confidence: RenderConfidence.UNKNOWN,\n };\n }\n\n /**\n * Diff props to find which keys changed and whether it's reference-only.\n * This is the key insight generator.\n */\n private diffProps(\n prevProps: Record<string, any> | null,\n nextProps: Record<string, any> | null\n ): PropChangeDetail[] {\n if (!prevProps || !nextProps) {\n return [];\n }\n\n const changes: PropChangeDetail[] = [];\n const allKeys = new Set([\n ...Object.keys(prevProps),\n ...Object.keys(nextProps),\n ]);\n\n const skipKeys = new Set([\"children\", \"key\", \"ref\"]);\n\n for (const key of allKeys) {\n if (skipKeys.has(key)) continue;\n\n const prevValue = prevProps[key];\n const nextValue = nextProps[key];\n\n if (prevValue === nextValue) {\n continue;\n }\n\n const referenceOnly = this.isShallowEqual(prevValue, nextValue);\n\n changes.push({ key, referenceOnly });\n\n if (changes.length >= 10) {\n break;\n }\n }\n\n return changes;\n }\n\n /**\n * Shallow equality check to determine if a prop is reference-only change.\n * We only go one level deep to keep it fast.\n */\n private isShallowEqual(a: any, b: any): boolean {\n // Same reference (already checked, but for safety)\n if (a === b) return true;\n\n // Different types\n if (typeof a !== typeof b) return false;\n\n // Null checks\n if (a === null || b === null) return false;\n\n // Functions - can't easily compare, assume different\n // But if they're both functions, it's likely a reference-only change\n // (same callback recreated)\n if (typeof a === \"function\" && typeof b === \"function\") {\n // We can't compare function bodies easily, but this is almost always\n // a reference-only change (inline callback recreated)\n return true; // Treat as reference-only\n }\n\n // Arrays\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) return false;\n\n for (const key of keysA) {\n if (a[key] !== b[key]) return false;\n }\n return true;\n }\n\n return a === b;\n }\n\n private isUserComponent(fiber: MinimalFiber): boolean {\n const tag = fiber.tag;\n return (\n tag === FiberTag.FunctionComponent ||\n tag === FiberTag.ClassComponent ||\n tag === FiberTag.ForwardRef ||\n tag === FiberTag.MemoComponent ||\n tag === FiberTag.SimpleMemoComponent\n );\n }\n\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n private getOrCreateComponentId(fiber: MinimalFiber): string {\n let id = this.fiberToComponentId.get(fiber);\n if (id) return id;\n\n if (fiber.alternate) {\n id = this.fiberToComponentId.get(fiber.alternate);\n if (id) {\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n }\n\n id = `c_${++this.componentIdCounter}`;\n this.fiberToComponentId.set(fiber, id);\n return id;\n }\n\n private getComponentName(fiber: MinimalFiber): string {\n const type = fiber.type;\n if (!type) return \"Unknown\";\n\n if (typeof type === \"function\") {\n return type.displayName || type.name || \"Anonymous\";\n }\n\n if (typeof type === \"object\" && type !== null) {\n if (type.displayName) return type.displayName;\n if (type.render)\n return type.render.displayName || type.render.name || \"ForwardRef\";\n if (type.type) {\n const inner = type.type;\n return inner.displayName || inner.name || \"Memo\";\n }\n }\n\n return \"Unknown\";\n }\n\n private getComponentType(fiber: MinimalFiber): ComponentType {\n switch (fiber.tag) {\n case FiberTag.FunctionComponent:\n return \"function\";\n case FiberTag.ClassComponent:\n return \"class\";\n case FiberTag.ForwardRef:\n return \"forwardRef\";\n case FiberTag.MemoComponent:\n case FiberTag.SimpleMemoComponent:\n return \"memo\";\n default:\n return \"unknown\";\n }\n }\n\n /**\n * Force emit current state (useful for debugging or on-demand refresh).\n */\n forceEmit(): void {\n this.emitSnapshot();\n }\n\n /**\n * Get current profile for a component (useful for debugging).\n */\n getProfile(componentId: string): ComponentProfile | undefined {\n return this.profiles.get(componentId);\n }\n\n /**\n * Get all suspicious components.\n */\n getSuspiciousComponents(): ComponentProfile[] {\n return Array.from(this.profiles.values()).filter((p) => p.isSuspicious);\n }\n\n cleanup(): void {\n if (!this.isSetup) return;\n\n this.emitSnapshot();\n\n if (this.snapshotTimer) {\n clearInterval(this.snapshotTimer);\n this.snapshotTimer = null;\n }\n\n if (this.originalHook) {\n if (this.originalOnCommitFiberRoot) {\n this.originalHook.onCommitFiberRoot = this.originalOnCommitFiberRoot;\n }\n if (this.originalOnCommitFiberUnmount) {\n this.originalHook.onCommitFiberUnmount =\n this.originalOnCommitFiberUnmount;\n }\n }\n\n this.originalHook = null;\n this.originalOnCommitFiberRoot = null;\n this.originalOnCommitFiberUnmount = null;\n this.profiles.clear();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n this.config = null;\n this.isSetup = false;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { SDK_VERSION } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.renderInterceptor = new RenderInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, console, and render interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: \"wss://api.getlimelight.io/limelight\",\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n enableRenderInspector: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n\n if (this.config.enableRenderInspector) {\n this.renderInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getlimelight/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "The react native debugger that actually works",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",