@getlimelight/sdk 0.7.9 → 0.7.10
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 +5 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +5 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/types/commands.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/detection/detectGlobalObject.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/helpers/graphql/normalizeOperationType.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/utils/environment.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/helpers/http/resolveUrl.ts","../src/helpers/http/isBinaryContentType.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/context/traceContext.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/HttpInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/interceptors/ErrorInterceptor.ts","../src/limelight/interceptors/StateInterceptor.ts","../src/limelight/bridges/RequestBridge.ts","../src/limelight/handlers/CommandHandler.ts","../src/limelight/middleware/httpMiddleware.ts","../src/limelight/middleware/withLimelight.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 INCOMING = \"incoming\",\n HTTP = \"http\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n ABORT = \"ABORT\",\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 traceId?: string; // correlates client → server → downstream events\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 | NetworkPhase.ABORT;\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 * Request with its corresponding response (for UI display)\n */\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\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","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","export enum CommandType {\n CLEAR_RENDERS = \"CLEAR_RENDERS\",\n ACK = \"ACK\",\n}\n\nexport interface BaseCommand {\n type: CommandType;\n id?: string;\n}\n\nexport interface ClearRendersCommand extends BaseCommand {\n type: CommandType.CLEAR_RENDERS;\n}\n\nexport type Command = ClearRendersCommand;\n\nexport interface CommandAckEvent {\n phase: CommandType.ACK;\n commandId: string;\n type: CommandType;\n success: boolean;\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","/**\n * Detects and returns the global object in various JavaScript environments.\n * @returns {typeof globalThis} The detected global object.\n */\nexport const detectGlobalObject = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") return globalThis;\n if (typeof window !== \"undefined\") return window;\n if (typeof global !== \"undefined\") return global;\n if (typeof self !== \"undefined\") return self;\n throw new Error(\"Unable to locate global object\");\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","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Normalizes various GraphQL operation type representations to a standard form.\n * @param type The operation type to normalize\n * @returns The normalized operation type or null if not provided\n */\nexport const normalizeOperationType = (\n type?: GraphqlOprtation | \"query\" | \"mutation\" | \"subscription\" | null,\n): GraphqlOprtation | null => {\n if (!type) return null;\n if (type === \"query\") return GraphqlOprtation.QUERY;\n if (type === \"mutation\") return GraphqlOprtation.MUTATION;\n if (type === \"subscription\") return GraphqlOprtation.SUB;\n\n return type;\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 WebSocket URL for Limelight web app connections.\n */\nexport const LIMELIGHT_WEB_WSS_URL = \"wss://api.getlimelight.io\";\n\n/**\n * The WebSocket URL for Limelight desktop app connections.\n */\nexport const LIMELIGHT_DESKTOP_WSS_URL = \"ws://localhost:8484\";\n\n/**\n * The WebSocket URL for Limelight MCP server connections.\n */\nexport const LIMELIGHT_MCP_WS_URL = \"ws://localhost:9229\";\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\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\n/**\n * Commonly used HTTP header names that are considered sensitive and should be redacted in Limelight messages.\n */\nexport const BINARY_CONTENT_TYPES = [\n \"image/\",\n \"audio/\",\n \"video/\",\n \"application/octet-stream\",\n \"application/pdf\",\n \"application/zip\",\n \"application/gzip\",\n];\n\n/**\n * Max body size for capture in Limelight. Requests or responses with bodies larger than this will have their body content truncated to avoid excessive memory usage.\n */\nexport const MAX_BODY_SIZE = 1024 * 1024; // 1MB cap for body capture\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, string>();\n\n const process = (val: unknown, currentDepth: number, path: string): 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 `[Symbol: ${val.description || \"\"}]`;\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 const seenPath = seen.get(val);\n\n if (seenPath !== undefined) {\n return `[Circular → ${seenPath}]`;\n }\n\n seen.set(val, path || \"root\");\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n ...Object.fromEntries(\n Object.entries(val).filter(\n ([k]) => ![\"name\", \"message\", \"stack\"].includes(k),\n ),\n ),\n };\n }\n\n if (val instanceof Date) {\n return { __type: \"Date\", value: val.toISOString() };\n }\n\n if (val instanceof RegExp) {\n return { __type: \"RegExp\", value: val.toString() };\n }\n\n if (val instanceof Map) {\n return {\n __type: \"Map\",\n size: val.size,\n entries: Array.from(val.entries()).map(([k, v], i) => [\n process(k, currentDepth + 1, `${path}.Map[${i}].key`),\n process(v, currentDepth + 1, `${path}.Map[${i}].value`),\n ]),\n };\n }\n\n if (val instanceof Set) {\n return {\n __type: \"Set\",\n size: val.size,\n values: Array.from(val).map((v, i) =>\n process(v, currentDepth + 1, `${path}.Set[${i}]`),\n ),\n };\n }\n\n if (val instanceof WeakMap) {\n return { __type: \"WeakMap\", note: \"[Contents not enumerable]\" };\n }\n if (val instanceof WeakSet) {\n return { __type: \"WeakSet\", note: \"[Contents not enumerable]\" };\n }\n\n if (val instanceof Promise) {\n return { __type: \"Promise\", note: \"[Pending state not accessible]\" };\n }\n\n if (val instanceof ArrayBuffer) {\n return { __type: \"ArrayBuffer\", byteLength: val.byteLength };\n }\n\n if (ArrayBuffer.isView(val)) {\n const typedArray = val as any;\n return {\n __type: val.constructor.name,\n length: typedArray.length ?? typedArray.byteLength,\n preview:\n typedArray.length <= 10\n ? Array.from(typedArray.slice?.(0, 10) ?? [])\n : `[${typedArray.length} items]`,\n };\n }\n\n if (typeof URL !== \"undefined\" && val instanceof URL) {\n return { __type: \"URL\", href: val.href };\n }\n\n if (\n typeof URLSearchParams !== \"undefined\" &&\n val instanceof URLSearchParams\n ) {\n return {\n __type: \"URLSearchParams\",\n entries: Object.fromEntries(val.entries()),\n };\n }\n\n if (\n val &&\n typeof (val as any).$$typeof === \"symbol\" &&\n String((val as any).$$typeof).includes(\"react.element\")\n ) {\n return {\n __type: \"ReactElement\",\n type:\n typeof (val as any).type === \"function\"\n ? (val as any).type.name || \"Component\"\n : (val as any).type || \"unknown\",\n key: (val as any).key,\n };\n }\n\n if (Array.isArray(val)) {\n return val.map((item, i) =>\n process(item, currentDepth + 1, `${path}[${i}]`),\n );\n }\n\n const result: Record<string, any> = {};\n const proto = Object.getPrototypeOf(val);\n\n if (proto && proto.constructor && proto.constructor.name !== \"Object\") {\n result.__type = proto.constructor.name;\n }\n\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n try {\n result[key] = process(\n (val as any)[key],\n currentDepth + 1,\n `${path}.${key}`,\n );\n } catch (e) {\n result[key] =\n `[Error accessing property: ${e instanceof Error ? e.message : String(e)}]`;\n }\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0, \"root\");\n return JSON.stringify(processed, null, pretty ? 2 : undefined);\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","/**\n * Returns true if DOM APIs are available (window + document).\n * True in browsers, false in Node.js and React Native.\n */\nexport const hasDOM = (): boolean =>\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\n/**\n * Returns true if running without DOM APIs (Node.js, React Native).\n */\nexport const isServer = (): boolean => !hasDOM();\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 type http from \"http\";\n\n/**\n * Resolves the full URL from the given HTTP request options.\n *\n * @param protocol The protocol to use (e.g. \"http:\" or \"https:\")\n * @param options The HTTP request options containing host, port, and path\n * @returns The fully resolved URL as a string\n */\nexport const resolveUrl = (\n protocol: string,\n options: http.RequestOptions,\n): string => {\n const host = options.hostname || options.host || \"localhost\";\n const port = options.port ? `:${options.port}` : \"\";\n const path = options.path || \"/\";\n return `${protocol}//${host}${port}${path}`;\n};\n","import { BINARY_CONTENT_TYPES } from \"@/constants\";\n\n/**\n * Checks if a given content type is considered binary.\n * @param {string} contentType - The content type to check.\n * @returns {boolean} True if the content type is binary, false otherwise.\n */\nexport const isBinaryContentType = (contentType: string): boolean => {\n return BINARY_CONTENT_TYPES.some((type) =>\n contentType.toLowerCase().includes(type),\n );\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n }\n\n return;\n }\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 // always log an error if beforeSend returns wrong type\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n }\n\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","export interface TraceStore {\n traceId: string;\n}\n\ninterface TraceContextLike {\n getStore(): TraceStore | undefined;\n run<T>(store: TraceStore, callback: (...args: any[]) => T, ...args: any[]): T;\n}\n\nlet _resolved = false;\nlet _traceContext: TraceContextLike | undefined;\n\n/**\n * Returns the AsyncLocalStorage-backed trace context if available (Node.js only).\n * Returns undefined in browser environments where AsyncLocalStorage is not available.\n *\n * @returns {TraceContextLike | undefined} The trace context or undefined if not available.\n */\nexport const getTraceContext = (): TraceContextLike | undefined => {\n if (!_resolved) {\n _resolved = true;\n try {\n // Use indirect require via globalThis so Metro/webpack can't\n // statically resolve and bundle this Node-only module.\n const _require = globalThis[\"require\"] as typeof require;\n const { AsyncLocalStorage } = _require(\"node:async_hooks\");\n\n _traceContext = new AsyncLocalStorage() as TraceContextLike;\n } catch {\n // Browser / React Native — AsyncLocalStorage not available\n }\n }\n\n return _traceContext;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n detectGlobalObject,\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch | undefined;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n private globalObject: typeof globalThis;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {\n this.globalObject = detectGlobalObject();\n if (typeof this.globalObject.fetch === \"function\") {\n this.originalFetch = this.globalObject.fetch.bind(this.globalObject);\n }\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n }\n\n return;\n }\n\n if (!this.originalFetch) {\n if (config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] fetch is not available in this environment, skipping network interception\",\n );\n }\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const originalFetch = this.originalFetch;\n\n this.globalObject.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 const traceHeaderName =\n self.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n\n if (!headers[traceHeaderName]) {\n const existingTraceId = getTraceContext()?.getStore()?.traceId;\n headers[traceHeaderName] = existingTraceId || generateRequestId();\n }\n\n const traceId = headers[traceHeaderName];\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\n if (self.config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Failed to read request body from Request object\",\n );\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 const rawBody = requestBody?.raw;\n\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\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 originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n // always log an error if beforeSend returns wrong type\n console.error(\"[Limelight] beforeSend must return same event type\");\n return originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await 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 traceId,\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 // always log an error if beforeSend returns wrong type\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 isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.message.includes(\"aborted\"));\n\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 traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: isAbort ? NetworkPhase.ABORT : NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: isAbort ? \"Request aborted\" : errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n }\n\n return;\n }\n\n this.isSetup = false;\n if (this.originalFetch) {\n this.globalObject.fetch = this.originalFetch;\n }\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 traceId?: 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 if (typeof XMLHttpRequest !== \"undefined\") {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\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 (typeof XMLHttpRequest === \"undefined\") {\n return;\n }\n\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n }\n\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 traceHeaderName =\n self.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n\n if (!data.headers[traceHeaderName]) {\n data.traceId = generateRequestId();\n self.originalXHRSetRequestHeader.call(\n this,\n traceHeaderName,\n data.traceId,\n );\n } else {\n data.traceId = data.headers[traceHeaderName];\n }\n\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture,\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n traceId: data.traceId,\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 // always log an error if beforeSend returns wrong type\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 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\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\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 traceId: data.traceId,\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 //always log an error if beforeSend returns wrong type\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 = (\n errorMessage: string,\n phase: NetworkPhase.ERROR | NetworkPhase.ABORT = NetworkPhase.ERROR,\n ) => {\n if (responseSent) return;\n\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n traceId: data.traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: phase,\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\", NetworkPhase.ABORT);\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 return;\n }\n this.isSetup = false;\n\n if (typeof XMLHttpRequest !== \"undefined\") {\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n }\n}\n","import type http from \"http\";\nimport type https from \"https\";\nimport {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isBinaryContentType,\n redactSensitiveHeaders,\n resolveUrl,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\nimport { MAX_BODY_SIZE } from \"@/constants\";\n\nexport class HttpInterceptor {\n private originalHttpRequest: typeof http.request | null = null;\n private originalHttpGet: typeof http.get | null = null;\n private originalHttpsRequest: typeof https.request | null = null;\n private originalHttpsGet: typeof https.get | null = null;\n\n private httpModule: typeof http | null = null;\n private httpsModule: typeof https | null = null;\n\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 try {\n const _require = globalThis[\"require\"] as typeof require;\n this.httpModule = _require(\"http\");\n this.httpsModule = _require(\"https\");\n\n this.originalHttpRequest = this.httpModule!.request;\n this.originalHttpGet = this.httpModule!.get;\n this.originalHttpsRequest = this.httpsModule!.request;\n this.originalHttpsGet = this.httpsModule!.get;\n } catch {\n // Browser / React Native - http module not available\n }\n }\n\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] HTTP interceptor already set up\");\n }\n\n return;\n }\n\n if (!this.httpModule || !this.httpsModule) {\n if (config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Node http module not available, skipping HTTP interception\",\n );\n }\n\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const httpMod = this.httpModule;\n const httpsMod = this.httpsModule;\n\n httpMod.request = (...args: any[]) => {\n return self.interceptRequest(\n \"http:\",\n self.originalHttpRequest!,\n httpMod,\n args,\n );\n };\n\n httpMod.get = (...args: any[]) => {\n const req = self.interceptRequest(\n \"http:\",\n self.originalHttpRequest!,\n httpMod,\n args,\n );\n req.end();\n return req;\n };\n\n httpsMod.request = (...args: any[]) => {\n return self.interceptRequest(\n \"https:\",\n self.originalHttpsRequest!,\n httpsMod,\n args,\n );\n };\n\n httpsMod.get = (...args: any[]) => {\n const req = self.interceptRequest(\n \"https:\",\n self.originalHttpsRequest!,\n httpsMod,\n args,\n );\n req.end();\n return req;\n };\n }\n\n private interceptRequest(\n protocol: string,\n originalMethod: typeof http.request,\n module: typeof http | typeof https,\n args: any[],\n ): http.ClientRequest {\n let url: string | URL | undefined;\n let options: http.RequestOptions;\n let callback: ((res: http.IncomingMessage) => void) | undefined;\n\n if (typeof args[0] === \"string\" || args[0] instanceof URL) {\n url = args[0];\n\n if (typeof args[1] === \"function\") {\n options = {};\n callback = args[1];\n } else {\n options = args[1] || {};\n callback = args[2];\n }\n } else {\n options = args[0] || {};\n callback = args[1];\n }\n\n let resolvedUrl: string;\n\n if (url) {\n resolvedUrl = url.toString();\n } else {\n resolvedUrl = resolveUrl(protocol, options);\n }\n\n const limelightServerUrl = this.config?.serverUrl || \"\";\n\n if (limelightServerUrl && resolvedUrl.includes(limelightServerUrl)) {\n return originalMethod.apply(module, args as any);\n }\n\n const self = this;\n const requestId = generateRequestId();\n const startTime = Date.now();\n const initiator = getInitiator();\n\n const traceHeaderName =\n this.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n const existingTraceId = getTraceContext()?.getStore()?.traceId;\n const traceId = existingTraceId || generateRequestId();\n\n if (!options.headers) {\n options.headers = {};\n }\n\n (options.headers as Record<string, string>)[traceHeaderName] = traceId;\n\n const method = (options.method || \"GET\").toUpperCase() as HttpMethod;\n\n let patchedArgs: any[];\n\n if (url) {\n patchedArgs = callback ? [url, options, callback] : [url, options];\n } else {\n patchedArgs = callback ? [options, callback] : [options];\n }\n\n const req: http.ClientRequest = originalMethod.apply(\n module,\n patchedArgs as any,\n );\n\n const bodyChunks: Buffer[] = [];\n let totalBodySize = 0;\n let requestEventSent = false;\n const originalWrite = req.write.bind(req);\n const originalEnd = req.end.bind(req);\n\n req.write = (\n chunk: any,\n encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),\n callback?: (error?: Error | null) => void,\n ): boolean => {\n if (chunk && totalBodySize < MAX_BODY_SIZE) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bodyChunks.push(buf);\n totalBodySize += buf.length;\n }\n return originalWrite(chunk, encodingOrCallback as any, callback as any);\n };\n\n req.end = (\n chunk?: any,\n encodingOrCallback?: BufferEncoding | (() => void),\n callback?: () => void,\n ): http.ClientRequest => {\n if (\n chunk &&\n typeof chunk !== \"function\" &&\n totalBodySize < MAX_BODY_SIZE\n ) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bodyChunks.push(buf);\n totalBodySize += buf.length;\n }\n\n if (!requestEventSent) {\n requestEventSent = true;\n\n const fullBody =\n bodyChunks.length > 0\n ? Buffer.concat(bodyChunks).toString(\"utf-8\")\n : undefined;\n\n const headers: Record<string, string> = {};\n const rawHeaders = req.getHeaders();\n\n for (const [key, value] of Object.entries(rawHeaders)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n }\n }\n\n const requestBody = serializeBody(\n fullBody,\n self.config?.disableBodyCapture,\n );\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.HTTP,\n url: resolvedUrl,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(resolvedUrl),\n initiator,\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 originalEnd(\n chunk,\n encodingOrCallback as any,\n callback as any,\n );\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return originalEnd(\n chunk,\n encodingOrCallback as any,\n callback as any,\n );\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n }\n\n return originalEnd(chunk, encodingOrCallback as any, callback as any);\n };\n\n let responseSent = false;\n\n req.on(\"response\", (res: http.IncomingMessage) => {\n const responseChunks: Buffer[] = [];\n let responseSize = 0;\n\n res.on(\"data\", (chunk: Buffer | string) => {\n if (responseSize < MAX_BODY_SIZE) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n responseChunks.push(buf);\n responseSize += buf.length;\n }\n });\n\n res.on(\"end\", () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const responseHeaders: Record<string, string> = {};\n\n if (res.headers) {\n for (const [key, value] of Object.entries(res.headers)) {\n if (value) {\n responseHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n }\n }\n\n const contentType = responseHeaders[\"content-type\"] || \"\";\n let responseBodyStr: string | undefined;\n\n if (responseChunks.length > 0) {\n if (isBinaryContentType(contentType)) {\n responseBodyStr = `[Binary Data: ${contentType}]`;\n } else {\n const full = Buffer.concat(responseChunks);\n responseBodyStr =\n full.length > MAX_BODY_SIZE\n ? full.toString(\"utf-8\", 0, MAX_BODY_SIZE) + \"...[truncated]\"\n : full.toString(\"utf-8\");\n }\n }\n\n const responseBody = serializeBody(\n responseBodyStr,\n self.config?.disableBodyCapture,\n );\n\n const statusCode = res.statusCode ?? 0;\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.HTTP,\n status: statusCode,\n statusText: res.statusMessage || \"\",\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: statusCode >= 200 && statusCode < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) return;\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n });\n });\n\n req.on(\"error\", (err: Error) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.HTTP,\n errorMessage: err.message || \"Network request failed\",\n stack: err.stack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n req.on(\"timeout\", () => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.HTTP,\n errorMessage: \"Request timeout\",\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n req.on(\"close\", () => {\n if (responseSent) return;\n if (!req.destroyed) return;\n\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ABORT,\n networkType: NetworkType.HTTP,\n errorMessage: \"Request aborted\",\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n return req;\n }\n\n cleanup() {\n if (!this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] HTTP interceptor not set up\");\n }\n return;\n }\n\n this.isSetup = false;\n\n if (this.httpModule && this.originalHttpRequest) {\n this.httpModule.request = this.originalHttpRequest;\n }\n\n if (this.httpModule && this.originalHttpGet) {\n this.httpModule.get = this.originalHttpGet;\n }\n\n if (this.httpsModule && this.originalHttpsRequest) {\n this.httpsModule.request = this.originalHttpsRequest;\n }\n\n if (this.httpsModule && this.originalHttpsGet) {\n this.httpsModule.get = this.originalHttpsGet;\n }\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} 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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n }\n\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Failed to install render hook\");\n }\n\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 /**\n * Installs or wraps the React DevTools global hook.\n * Returns true if successful, false otherwise.\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 /**\n * Wraps an existing React DevTools hook to intercept render events.\n * Preserves original functionality.\n * @param hook - The existing React DevTools hook\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 /**\n * Creates a new React DevTools hook to intercept render events.\n * @param globalObj - The global object (window or global)\n * @param hookKey - The key for the React DevTools hook\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 * @param rendererID - The renderer ID\n * @param root - The fiber root\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 (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n * @param fiber - The current fiber node\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 /**\n * Handles a fiber unmount - marks component as unmounted.\n * @param rendererID - The renderer ID\n * @param fiber - The fiber being unmounted\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 * @param fiber - The current fiber node\n * @param parentComponentId - The parent component ID\n * @param depth - The current depth in the tree\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number,\n ): void {\n if (!fiber) return;\n\n let currentParentId = parentComponentId;\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 currentParentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, currentParentId, 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 * @param fiber - The current fiber node\n * @param componentId - The component ID\n * @param parentComponentId - The parent component ID\n * @param depth - The current depth in the tree\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 * Accumulate prop change details into the profile.\n * @param profile - The component profile\n * @param changes - The list of prop change details\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 * @param profile - The component profile\n * @returns The prop change snapshot or undefined\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 /**\n * Updates the suspicious flag based on render velocity and count.\n * @param profile - The component profile\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 * @param profile - The component profile\n * @returns The calculated velocity\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 * Only emits profiles that have significant changes since last emit.\n * Also emits unmounts.\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 * Infers the cause of the render by comparing current and previous fiber states.\n * @param fiber - The current fiber node\n * @param parentComponentId - The parent component ID\n * @returns The inferred render cause\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 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 * @param prevProps - The previous props\n * @param nextProps - The next props\n * @returns List of prop change details\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 * @param a - The first value\n * @param b - The second value\n * @returns True if shallow equal, false otherwise\n */\n private isShallowEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (typeof a !== typeof b) return false;\n\n if (a === null || b === null) return false;\n\n if (typeof a === \"function\" && typeof b === \"function\") {\n return true;\n }\n\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 /**\n * Determines if a fiber represents a user-defined component.\n * @param fiber - The fiber node\n * @returns True if user component, false otherwise\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 /**\n * Determines if a fiber performed work during the commit.\n * @param fiber - The fiber node\n * @returns True if performed work, false otherwise\n */\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n /**\n * Gets or creates a unique component ID for a fiber.\n * @param fiber - The fiber node\n * @returns The unique component ID\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 /**\n * Gets the display name of a component from a fiber.\n * @param fiber - The fiber node\n * @returns The component name\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 /**\n * Gets the component type from a fiber.\n * @param fiber - The fiber node\n * @returns The component type\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 /**\n * Cleans up and restores original hook behavior.\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 /**\n * Resets all collected profiles\n */\n resetProfiles(): void {\n this.profiles.clear();\n this.fiberToComponentId = new WeakMap<MinimalFiber, string>();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n }\n}\n","import { safeStringify } from \"@/helpers\";\nimport {\n ConsoleLevel,\n ConsoleSource,\n ConsoleType,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\n/**\n * Captures uncaught exceptions and unhandled promise rejections in Node.js\n * and sends them as CONSOLE error events through the Limelight protocol.\n *\n * Only activates in server environments where `process` is available.\n */\nexport class ErrorInterceptor {\n private isSetup = false;\n private config: LimelightConfig | null = null;\n private counter = 0;\n\n private uncaughtExceptionHandler: ((error: Error) => void) | null = null;\n private unhandledRejectionHandler:\n | ((reason: unknown, promise: Promise<unknown>) => void)\n | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {}\n\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Error interceptor already set up\");\n }\n return;\n }\n\n if (typeof process === \"undefined\" || !process.on) {\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n this.uncaughtExceptionHandler = (error: Error) => {\n this.sendErrorEvent(error, \"uncaughtException\");\n // Give the WebSocket time to actually send the error event over the wire\n // before exiting. 200ms is enough for a local/LAN WebSocket flush.\n setTimeout(() => {\n process.exit(1);\n }, 200);\n };\n\n this.unhandledRejectionHandler = (reason: unknown) => {\n const error =\n reason instanceof Error ? reason : new Error(String(reason));\n this.sendErrorEvent(error, \"unhandledRejection\");\n };\n\n process.on(\"uncaughtException\", this.uncaughtExceptionHandler);\n process.on(\"unhandledRejection\", this.unhandledRejectionHandler);\n }\n\n cleanup() {\n if (!this.isSetup) return;\n\n this.isSetup = false;\n\n if (this.uncaughtExceptionHandler) {\n process.removeListener(\n \"uncaughtException\",\n this.uncaughtExceptionHandler,\n );\n this.uncaughtExceptionHandler = null;\n }\n\n if (this.unhandledRejectionHandler) {\n process.removeListener(\n \"unhandledRejection\",\n this.unhandledRejectionHandler,\n );\n this.unhandledRejectionHandler = null;\n }\n\n this.config = null;\n }\n\n private sendErrorEvent(error: Error, source: string) {\n const sessionId = this.getSessionId();\n\n const event: LimelightMessage = {\n id: `${sessionId}-${Date.now()}-${this.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: ConsoleLevel.ERROR,\n timestamp: Date.now(),\n sessionId,\n source: ConsoleSource.APP,\n consoleType: ConsoleType.EXCEPTION,\n args: [safeStringify(`[${source}] ${error.message}`)],\n stackTrace: error.stack,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(event);\n\n if (!modified) return;\n }\n\n this.sendMessage(event);\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n StateLibrary,\n StatePhase,\n StateInitEvent,\n StateUpdateEvent,\n StateAction,\n} from \"@/types/state\";\n\ninterface RegisteredStore {\n name: string;\n library: StateLibrary;\n unsubscribe: () => void;\n}\n\nexport class StateInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private stores: Map<string, RegisteredStore> = new Map();\n private config: LimelightConfig | null = null;\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 this.config = config;\n\n if (!config.stores) return;\n if (config.enableStateInspector === false) return;\n\n for (const [name, store] of Object.entries(config.stores)) {\n this.registerStore(name, store);\n }\n }\n\n /**\n * Register a store for inspection.\n * Can be called manually via Limelight.addStore() for dynamic registration.\n */\n registerStore(name: string, store: unknown): void {\n if (this.stores.has(name)) {\n if (this.config?.enableInternalLogging) {\n console.warn(`[Limelight] Store \"${name}\" already registered`);\n }\n\n return;\n }\n\n const library = this.detectLibrary(store);\n\n if (!library) {\n //always log warning if store type cannot be detected\n console.warn(\n `[Limelight] Could not detect store type for \"${name}\". Expected Zustand or Redux store.`,\n );\n return;\n }\n\n const state = this.getState(store);\n\n const initEvent: StateInitEvent = {\n phase: StatePhase.INIT,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: name,\n library,\n state,\n },\n };\n\n this.emitEvent(initEvent);\n\n const unsubscribe = this.subscribe(store, library, name);\n\n this.stores.set(name, { name, library, unsubscribe });\n }\n\n /**\n * Unregister a store and stop listening to changes.\n * Can be called manually via Limelight.removeStore().\n * @param name The name of the store to unregister\n */\n unregisterStore(name: string): void {\n const store = this.stores.get(name);\n if (store) {\n store.unsubscribe();\n this.stores.delete(name);\n }\n }\n\n /**\n * Emit an event, applying beforeSend hook if configured\n * @param event The event to emit\n */\n private emitEvent(event: StateInitEvent | StateUpdateEvent): void {\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(event);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (\n modifiedEvent.phase !== StatePhase.INIT &&\n modifiedEvent.phase !== StatePhase.UPDATE\n ) {\n // always log an error if beforeSend returns wrong type\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n this.sendMessage(modifiedEvent);\n } else {\n this.sendMessage(event);\n }\n }\n\n /**\n * Detect whether a store is Zustand or Redux\n * @param store The store to inspect\n * @return StateLibrary or null if unknown\n */\n private detectLibrary(store: unknown): StateLibrary | null {\n if (!store || (typeof store !== \"function\" && typeof store !== \"object\")) {\n return null;\n }\n\n // Redux stores have dispatch, getState, subscribe, and replaceReducer\n if (\n typeof store === \"object\" &&\n \"dispatch\" in store &&\n \"getState\" in store &&\n \"subscribe\" in store &&\n typeof (store as any).dispatch === \"function\"\n ) {\n return StateLibrary.REDUX;\n }\n\n // Zustand stores are functions with getState and subscribe\n if (\n typeof store === \"function\" &&\n \"getState\" in store &&\n \"subscribe\" in store &&\n typeof (store as any).getState === \"function\"\n ) {\n return StateLibrary.ZUSTAND;\n }\n\n // Vanilla Zustand stores (created with createStore instead of create)\n if (\n typeof store === \"object\" &&\n \"getState\" in store &&\n \"setState\" in store &&\n \"subscribe\" in store &&\n !(\"dispatch\" in store)\n ) {\n return StateLibrary.ZUSTAND;\n }\n\n return null;\n }\n\n /**\n * Get current state from a store\n * @param store The store to get state from\n * @return The current state\n */\n private getState(store: unknown): unknown {\n const storeAny = store as any;\n return storeAny.getState();\n }\n\n /**\n * Subscribe to store changes\n * @param store The store to subscribe to\n * @param library The detected state library\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribe(\n store: unknown,\n library: StateLibrary,\n storeName: string,\n ): () => void {\n const storeAny = store as any;\n\n if (library === StateLibrary.ZUSTAND) {\n return this.subscribeZustand(storeAny, storeName);\n } else {\n return this.subscribeRedux(storeAny, storeName);\n }\n }\n\n /**\n * Subscribe to Zustand store changes\n * @param store The Zustand store\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribeZustand(store: any, storeName: string): () => void {\n return store.subscribe((state: unknown, prevState: unknown) => {\n const action = this.inferZustandAction(state, prevState);\n const stackTrace = this.captureStackTrace();\n\n const updateEvent: StateUpdateEvent = {\n phase: StatePhase.UPDATE,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: storeName,\n library: StateLibrary.ZUSTAND,\n state,\n action,\n stackTrace,\n },\n };\n\n this.emitEvent(updateEvent);\n });\n }\n\n /**\n * Subscribe to Redux store changes\n * @param store The Redux store\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribeRedux(store: any, storeName: string): () => void {\n let lastAction: StateAction = { type: \"@@INIT\" };\n\n const originalDispatch = store.dispatch;\n store.dispatch = (action: any) => {\n lastAction = {\n type: action?.type || \"unknown\",\n payload: action?.payload,\n };\n return originalDispatch(action);\n };\n\n const unsubscribe = store.subscribe(() => {\n const newState = store.getState();\n const stackTrace = this.captureStackTrace();\n\n const updateEvent: StateUpdateEvent = {\n phase: StatePhase.UPDATE,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: storeName,\n library: StateLibrary.REDUX,\n state: newState,\n action: lastAction,\n stackTrace,\n },\n };\n\n this.emitEvent(updateEvent);\n });\n\n return () => {\n unsubscribe();\n store.dispatch = originalDispatch;\n };\n }\n\n /**\n * Infer action name from stack trace for Zustand\n * @param state The new state\n * @param prevState The previous state\n * @return Inferred StateAction\n */\n private inferZustandAction(state: unknown, prevState: unknown): StateAction {\n const actionType = this.parseActionFromStack(this.captureStackTrace());\n const payload = this.computePartialState(state, prevState);\n\n return {\n type: actionType,\n payload,\n };\n }\n\n /**\n * Parse function name from stack trace\n * @param stack The stack trace string\n * @return The inferred action name\n */\n private parseActionFromStack(stack?: string): string {\n if (!stack) return \"set\";\n\n const lines = stack.split(\"\\n\");\n\n for (const line of lines) {\n if (line.includes(\"node_modules/zustand\")) continue;\n if (line.includes(\"node_modules/immer\")) continue;\n if (line.includes(\"StateInterceptor\")) continue;\n if (line.includes(\"limelight\")) continue;\n\n // V8 format\n const v8Match =\n line.match(/at\\s+(?:Object\\.)?(\\w+)\\s+\\(/) ||\n line.match(/at\\s+(\\w+)\\s*\\[/) ||\n line.match(/at\\s+(\\w+)/);\n\n // Hermes format\n const hermesMatch = line.match(/^(\\w+)@/);\n\n const match = v8Match || hermesMatch;\n\n if (match && match[1]) {\n const name = match[1];\n if (\n ![\n \"anonymous\",\n \"Object\",\n \"Array\",\n \"Function\",\n \"eval\",\n \"Error\",\n ].includes(name)\n ) {\n return name;\n }\n }\n }\n\n return \"set\";\n }\n\n /**\n * Compute what keys changed between states (shallow)\n * @param state The new state\n * @param prevState The previous state\n * @return Partial state with only changed keys\n */\n private computePartialState(state: unknown, prevState: unknown): unknown {\n if (\n typeof state !== \"object\" ||\n state === null ||\n typeof prevState !== \"object\" ||\n prevState === null\n ) {\n return state;\n }\n\n const partial: Record<string, unknown> = {};\n const stateObj = state as Record<string, unknown>;\n const prevObj = prevState as Record<string, unknown>;\n\n for (const key of Object.keys(stateObj)) {\n if (stateObj[key] !== prevObj[key]) {\n partial[key] = stateObj[key];\n }\n }\n\n if (Object.keys(partial).length === 0) {\n return state;\n }\n\n return partial;\n }\n\n /**\n * Capture current stack trace\n */\n private captureStackTrace(): string | undefined {\n try {\n const err = new Error();\n return err.stack;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Cleanup all subscriptions\n */\n cleanup(): void {\n for (const [, store] of this.stores) {\n store.unsubscribe();\n }\n this.stores.clear();\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n NetworkPhase,\n NetworkType,\n NetworkRequest,\n NetworkResponse,\n NetworkErrorEvent,\n HttpMethod,\n} from \"@/types\";\nimport {\n serializeBody,\n redactSensitiveHeaders,\n formatRequestName,\n normalizeOperationType,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport {\n RequestBridgeConfig,\n ResponseBridgeConfig,\n} from \"@/types/request-bridge\";\n\ninterface PendingRequest {\n startTime: number;\n config: RequestBridgeConfig;\n}\n\nexport class RequestBridge {\n private pendingRequests = new Map<string, PendingRequest>();\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {\n // No-op\n }\n\n /**\n * Updates the config reference (called when LimelightClient configures)\n * @param config The new Limelight configuration or null to disable\n */\n setConfig(config: LimelightConfig | null) {\n this.config = config;\n }\n\n /**\n * Starts tracking a manual request. Returns a requestId to use with endRequest/failRequest.\n * @param config The request configuration\n * @returns The generated request ID\n */\n startRequest(config: RequestBridgeConfig): string {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n this.pendingRequests.set(requestId, { startTime, config });\n\n let bodyToSerialize = config.body;\n\n if (config.graphql && !config.body) {\n bodyToSerialize = JSON.stringify({\n operationName: config.graphql.operationName,\n variables: config.graphql.variables,\n query: config.graphql.query,\n });\n }\n\n const method = (config.method?.toUpperCase() || \"POST\") as HttpMethod;\n const headers = config.headers || {};\n\n const requestBody = serializeBody(\n typeof bodyToSerialize === \"string\"\n ? bodyToSerialize\n : JSON.stringify(bodyToSerialize),\n this.config?.disableBodyCapture,\n );\n\n let requestEvent: NetworkRequest = {\n id: requestId,\n sessionId: this.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url: config.url,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: config.name || formatRequestName(config.url),\n initiator: \"manual\",\n requestSize: requestBody?.size ?? 0,\n graphql: config.graphql\n ? {\n operationName: config.graphql.operationName,\n operationType: normalizeOperationType(config.graphql.operationType),\n variables: config.graphql.variables,\n query: config.graphql.query,\n }\n : undefined,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n this.pendingRequests.delete(requestId);\n return requestId;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return requestId;\n }\n\n requestEvent = modifiedEvent as NetworkRequest;\n }\n\n this.sendMessage(requestEvent);\n\n return requestId;\n }\n\n /**\n * Completes a tracked request with a successful response.\n * @param requestId The ID returned from startRequest\n * @param response The response data\n */\n endRequest(requestId: string, response: ResponseBridgeConfig): void {\n const pending = this.pendingRequests.get(requestId);\n\n if (!pending) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n `[Limelight] No pending request found for id: ${requestId}`,\n );\n }\n return;\n }\n\n this.pendingRequests.delete(requestId);\n\n const endTime = Date.now();\n const duration = endTime - pending.startTime;\n\n const responseHeaders = response.headers || {};\n const responseBody = serializeBody(\n typeof response.body === \"string\"\n ? response.body\n : JSON.stringify(response.body),\n this.config?.disableBodyCapture,\n );\n\n let responseEvent: NetworkResponse = {\n id: requestId,\n sessionId: this.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: false,\n ok: response.status >= 200 && response.status < 300,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modifiedEvent as NetworkResponse;\n }\n\n this.sendMessage(responseEvent);\n }\n\n /**\n * Completes a tracked request with an error.\n * @param requestId The ID returned from startRequest\n * @param error The error object or message\n */\n failRequest(requestId: string, error: unknown): void {\n const pending = this.pendingRequests.get(requestId);\n\n if (!pending) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n `[Limelight] No pending request found for id: ${requestId}`,\n );\n }\n return;\n }\n\n this.pendingRequests.delete(requestId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage,\n stack: errorStack,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent as NetworkErrorEvent;\n }\n }\n\n this.sendMessage(errorEvent);\n }\n\n /**\n * Cleans up any pending requests (called on disconnect)\n */\n cleanup() {\n this.pendingRequests.clear();\n }\n}\n","// limelight/CommandHandler.ts\nimport { Command, CommandType, LimelightMessage } from \"@/types\";\nimport { RenderInterceptor } from \"../interceptors\";\n\nexport class CommandHandler {\n constructor(\n private interceptors: {\n render: RenderInterceptor;\n },\n private sendMessage: (message: LimelightMessage) => void,\n private getConfig: () => { enableInternalLogging?: boolean } | null,\n ) {\n // No-op\n }\n\n /**\n * Handles an incoming command.\n * @param command - The command to handle\n */\n handle(command: Command): void {\n const config = this.getConfig();\n\n if (config?.enableInternalLogging) {\n console.log(\"[Limelight] Received command:\", command.type);\n }\n\n switch (command.type) {\n case CommandType.CLEAR_RENDERS:\n this.interceptors.render.resetProfiles();\n break;\n\n default:\n if (config?.enableInternalLogging) {\n console.warn(\"[Limelight] Unknown command:\", command.type);\n }\n }\n\n if (command.id) {\n this.sendMessage({\n phase: CommandType.ACK,\n commandId: command.id,\n type: command.type,\n success: true,\n });\n }\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"http\";\nimport {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport { redactSensitiveHeaders, serializeBody } from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\n\nconst DEFAULT_MAX_BODY_SIZE = 64 * 1024; // 64KB\n\nexport interface MiddlewareOptions {\n /** Maximum body size to capture in bytes. Bodies larger than this are truncated. Default: 64KB */\n maxBodySize?: number;\n}\n\n/**\n * Captures incoming request data and sends REQUEST/RESPONSE events through\n * the Limelight message protocol. Shared logic used by both Express middleware\n * and Next.js wrapper.\n *\n * @param req Incoming HTTP request object (Node.js IncomingMessage)\n * @param res HTTP response object (Node.js ServerResponse)\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param config Current Limelight configuration object\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns void\n */\nexport const captureRequest = (\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n config: LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n const requestId = generateRequestId();\n const startTime = Date.now();\n const maxBodySize = options?.maxBodySize ?? DEFAULT_MAX_BODY_SIZE;\n\n const traceHeaderName = config?.traceHeaderName ?? \"x-limelight-trace-id\";\n const incomingTraceId = req.headers[traceHeaderName] as string | undefined;\n const traceId = incomingTraceId || generateRequestId();\n (req as any).limelightTraceId = traceId;\n\n const url = req.url || \"/\";\n const method = (req.method || \"GET\").toUpperCase() as HttpMethod;\n\n const headers: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n headers[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n }\n\n let requestBody = serializeBody(req.body, config?.disableBodyCapture);\n\n if (requestBody?.raw && requestBody.raw.length > maxBodySize) {\n requestBody = {\n ...requestBody,\n raw: requestBody.raw.slice(0, maxBodySize) + \"...[truncated]\",\n size: requestBody.size,\n };\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.INCOMING,\n url,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: url.split(\"?\")[0]?.split(\"/\").filter(Boolean).pop() ?? \"/\",\n initiator: \"incoming\",\n requestSize: requestBody?.size ?? 0,\n };\n\n if (config?.beforeSend) {\n const modified = config.beforeSend(requestEvent);\n\n if (!modified) return;\n if (modified.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n requestEvent = modified;\n }\n\n sendMessage(requestEvent);\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n const originalWrite = res.write;\n const originalEnd = res.end;\n\n res.write = (chunk: any, ...args: any[]): boolean => {\n if (chunk && typeof chunk !== \"function\" && totalSize < maxBodySize) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buf);\n totalSize += buf.length;\n }\n\n return originalWrite.apply(res, [chunk, ...args] as any);\n };\n\n res.end = (chunk: any, ...args: any[]): ServerResponse => {\n if (chunk && typeof chunk !== \"function\" && totalSize < maxBodySize) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buf);\n totalSize += buf.length;\n }\n\n return originalEnd.apply(res, [chunk, ...args] as any);\n };\n\n res.on(\"finish\", () => {\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const responseHeaders: Record<string, string> = {};\n const rawHeaders = res.getHeaders();\n\n for (const [key, value] of Object.entries(rawHeaders)) {\n if (value) {\n responseHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n }\n }\n\n let responseBodyStr: string | undefined;\n\n if (chunks.length > 0 && !config?.disableBodyCapture) {\n const full = Buffer.concat(chunks);\n const fullStr = full.toString(\"utf-8\");\n\n responseBodyStr =\n fullStr.length > maxBodySize\n ? fullStr.slice(0, maxBodySize) + \"...[truncated]\"\n : fullStr;\n }\n\n const responseBody = serializeBody(\n responseBodyStr,\n config?.disableBodyCapture,\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.INCOMING,\n status: res.statusCode,\n statusText: res.statusMessage || \"\",\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: res.statusCode >= 200 && res.statusCode < 300,\n };\n\n if (config?.beforeSend) {\n const modified = config.beforeSend(responseEvent);\n if (!modified) return;\n\n if (modified.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modified;\n }\n\n sendMessage(responseEvent);\n });\n};\n\n/**\n * Creates an Express/Connect-compatible middleware that captures incoming\n * HTTP requests and responses, sending them through the Limelight protocol.\n *\n * Place this middleware AFTER body-parser middleware (express.json(), etc.)\n * so that req.body is available for request body capture.\n *\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param getConfig Function to retrieve the current Limelight configuration\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns An Express/Connect middleware function\n */\nexport const createHttpMiddleware = (\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n getConfig: () => LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n return (\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n next: () => void,\n ) => {\n captureRequest(req, res, sendMessage, getSessionId, getConfig(), options);\n\n const traceId = (req as any).limelightTraceId as string | undefined;\n const ctx = getTraceContext();\n\n if (ctx && traceId) {\n ctx.run({ traceId }, next);\n } else {\n next();\n }\n };\n};\n","import type { IncomingMessage, ServerResponse } from \"http\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport { captureRequest, MiddlewareOptions } from \"./httpMiddleware\";\nimport { getTraceContext } from \"@/limelight/context\";\n\ntype NextApiHandler = (\n req: IncomingMessage & { body?: unknown; query?: Record<string, unknown> },\n res: ServerResponse,\n) => void | Promise<void>;\n\n/**\n * Wraps a Next.js Pages API route handler with Limelight request/response capture.\n *\n * NOTE: This works with Next.js Pages Router API routes (`pages/api/`)\n * which use the Node.js `(req, res)` signature. It does NOT work with\n * App Router route handlers (`app/api/`) which use the Web Standard\n * `Request`/`Response` objects. App Router support is planned for a future release.\n *\n * @example\n * ```ts\n * // pages/api/users.ts\n * import { Limelight } from '@getlimelight/sdk';\n *\n * export default Limelight.withLimelight((req, res) => {\n * res.json({ ok: true });\n * });\n * ```\n *\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param getConfig Function to retrieve the current Limelight configuration\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns A function that wraps a Next.js API route handler with Limelight capture\n */\nexport const createWithLimelight = (\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n getConfig: () => LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n return (handler: NextApiHandler): NextApiHandler => {\n return (req, res) => {\n captureRequest(req, res, sendMessage, getSessionId, getConfig(), options);\n\n const traceId = (req as any).limelightTraceId as string | undefined;\n const ctx = getTraceContext();\n\n if (ctx && traceId) {\n return ctx.run({ traceId }, () => handler(req, res));\n }\n\n return handler(req, res);\n };\n };\n};\n","import {\n LimelightConfig,\n LimelightMessage,\n RequestBridgeConfig,\n ResponseBridgeConfig,\n} from \"@/types\";\nimport {\n ConsoleInterceptor,\n ErrorInterceptor,\n HttpInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { hasDOM, isDevelopment, safeStringify } from \"@/helpers\";\nimport {\n LIMELIGHT_DESKTOP_WSS_URL,\n LIMELIGHT_MCP_WS_URL,\n LIMELIGHT_WEB_WSS_URL,\n SDK_VERSION,\n WS_PATH,\n} from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\nimport { StateInterceptor } from \"./interceptors/StateInterceptor\";\nimport { RequestBridge } from \"./bridges/RequestBridge\";\nimport { CommandHandler } from \"./handlers/CommandHandler\";\nimport { Command } from \"@/types/commands\";\nimport {\n createHttpMiddleware,\n createWithLimelight,\n MiddlewareOptions,\n} from \"./middleware\";\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 httpInterceptor: HttpInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n private stateInterceptor: StateInterceptor;\n private errorInterceptor: ErrorInterceptor;\n private requestBridge: RequestBridge;\n private commandHandler: CommandHandler | null = null;\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.httpInterceptor = new HttpInterceptor(\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 this.stateInterceptor = new StateInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.errorInterceptor = new ErrorInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.requestBridge = new RequestBridge(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.commandHandler = new CommandHandler(\n { render: this.renderInterceptor },\n this.sendMessage.bind(this),\n () => this.config,\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 const configServerUrl = config?.serverUrl\n ? config.serverUrl\n : config?.target === \"mcp\"\n ? LIMELIGHT_MCP_WS_URL\n : config?.projectKey\n ? `${LIMELIGHT_WEB_WSS_URL}${WS_PATH}`\n : `${LIMELIGHT_DESKTOP_WSS_URL}${WS_PATH}`;\n\n this.config = {\n ...config,\n appName: config?.appName ?? \"Limelight App\",\n serverUrl: configServerUrl,\n enabled: isEnabled,\n enableNetworkInspector: config?.enableNetworkInspector ?? true,\n enableConsole: config?.enableConsole ?? true,\n enableGraphQL: config?.enableGraphQL ?? true,\n enableRenderInspector: config?.enableRenderInspector ?? true,\n enableStateInspector: config?.enableStateInspector ?? true,\n enableInternalLogging: config?.enableInternalLogging ?? false,\n };\n\n if (!this.config?.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n this.requestBridge.setConfig(this.config);\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n\n if (typeof XMLHttpRequest !== \"undefined\") {\n this.xhrInterceptor.setup(this.config);\n }\n\n if (!hasDOM()) {\n this.httpInterceptor.setup(this.config);\n }\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n\n if (!hasDOM()) {\n this.errorInterceptor.setup(this.config);\n }\n }\n\n if (this.config.enableRenderInspector && hasDOM()) {\n this.renderInterceptor.setup(this.config);\n }\n\n if (this.config.stores && this.config.enableStateInspector) {\n this.stateInterceptor.setup(this.config);\n }\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\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 this.configure(config);\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === 1 /* WebSocket.OPEN */) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n }\n\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 this.ws = null;\n }\n\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n }\n return;\n }\n\n const WsConstructor =\n this.config.webSocketImpl ??\n (typeof WebSocket !== \"undefined\" ? WebSocket : undefined);\n\n if (!WsConstructor) {\n if (this.config?.enableInternalLogging) {\n console.error(\n \"[Limelight] WebSocket is not available. Pass webSocketImpl in config (e.g. ws package).\",\n );\n }\n return;\n }\n\n try {\n this.ws = new WsConstructor(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 (hasDOM()\n ? \"web\"\n : typeof process !== \"undefined\"\n ? \"node\"\n : \"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.onmessage = (event) => {\n try {\n const command = JSON.parse(event.data) as Command;\n this.commandHandler?.handle(command);\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to parse command:\", error);\n }\n }\n };\n\n this.ws.onerror = (error) => {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] WebSocket error:\", error);\n }\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to connect:\", error);\n }\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\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 this.connect(this.config || undefined);\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 !== 1 /* WebSocket.OPEN */) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n // Patch sessionId for messages queued before connect()\n if (message && \"sessionId\" in message && !message.sessionId) {\n (message as any).sessionId = this.sessionId;\n }\n this.ws.send(safeStringify(message));\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\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 === 1 /* WebSocket.OPEN */) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === 1 /* WebSocket.OPEN */) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to send message:\", error);\n }\n\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Message queue full, dropping oldest message\",\n );\n }\n\n this.messageQueue.shift();\n }\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 if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.httpInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.errorInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n this.stateInterceptor.cleanup();\n this.requestBridge.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 /**\n * Manually register a request with Limelight.\n * Use this when your app makes network requests outside of fetch/XHR\n * (e.g., through native modules).\n *\n * @param config - Request configuration\n * @returns A request ID to use with endRequest() or failRequest()\n */\n startRequest(config: RequestBridgeConfig): string {\n return this.requestBridge.startRequest(config);\n }\n\n /**\n * Complete a manually tracked request with a successful response.\n *\n * @param requestId - The ID returned from startRequest()\n * @param response - Response data\n */\n endRequest(requestId: string, response: ResponseBridgeConfig): void {\n this.requestBridge.endRequest(requestId, response);\n }\n\n /**\n * Complete a manually tracked request with an error.\n *\n * @param requestId - The ID returned from startRequest()\n * @param error - The error that occurred\n */\n failRequest(requestId: string, error: unknown): void {\n this.requestBridge.failRequest(requestId, error);\n }\n\n /**\n * Returns an Express/Connect-compatible middleware that captures incoming\n * HTTP requests and responses.\n *\n * Place after body-parser middleware (express.json(), etc.) for request body capture.\n *\n * @example\n * ```ts\n * app.use(express.json());\n * app.use(Limelight.middleware());\n * ```\n */\n middleware(options?: MiddlewareOptions) {\n return createHttpMiddleware(\n this.sendMessage.bind(this),\n () => this.sessionId,\n () => this.config,\n options,\n );\n }\n\n /**\n * Wraps a Next.js Pages API route handler with request/response capture.\n * Works with Pages Router (`pages/api/`), not App Router (`app/api/`).\n *\n * @example\n * ```ts\n * // pages/api/users.ts\n * export default Limelight.withLimelight((req, res) => {\n * res.json({ ok: true });\n * });\n * ```\n */\n withLimelight(\n handler: Parameters<ReturnType<typeof createWithLimelight>>[0],\n ) {\n const wrapper = createWithLimelight(\n this.sendMessage.bind(this),\n () => this.sessionId,\n () => this.config,\n );\n return wrapper(handler);\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\nexport type { RequestBridgeConfig, LimelightConfig, LimelightMessage };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","CommandType","process","self","self","self","self","callback"]}
|
|
1
|
+
{"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/types/commands.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/detection/detectGlobalObject.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/helpers/graphql/normalizeOperationType.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/utils/environment.ts","../src/helpers/render/generateRenderId.ts","../src/helpers/render/createEmptyCauseBreakdown.ts","../src/helpers/render/createEmptyPropChangeStats.ts","../src/helpers/render/getCurrentTransactionId.ts","../src/helpers/http/resolveUrl.ts","../src/helpers/http/isBinaryContentType.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/context/traceContext.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/interceptors/HttpInterceptor.ts","../src/limelight/interceptors/RenderInterceptor.ts","../src/limelight/interceptors/ErrorInterceptor.ts","../src/limelight/interceptors/StateInterceptor.ts","../src/limelight/bridges/RequestBridge.ts","../src/limelight/handlers/CommandHandler.ts","../src/limelight/middleware/httpMiddleware.ts","../src/limelight/middleware/withLimelight.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 INCOMING = \"incoming\",\n HTTP = \"http\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n ABORT = \"ABORT\",\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 traceId?: string; // correlates client → server → downstream events\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 | NetworkPhase.ABORT;\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 * Request with its corresponding response (for UI display)\n */\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\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","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","export enum CommandType {\n CLEAR_RENDERS = \"CLEAR_RENDERS\",\n ACK = \"ACK\",\n}\n\nexport interface BaseCommand {\n type: CommandType;\n id?: string;\n}\n\nexport interface ClearRendersCommand extends BaseCommand {\n type: CommandType.CLEAR_RENDERS;\n}\n\nexport type Command = ClearRendersCommand;\n\nexport interface CommandAckEvent {\n phase: CommandType.ACK;\n commandId: string;\n type: CommandType;\n success: boolean;\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","/**\n * Detects and returns the global object in various JavaScript environments.\n * @returns {typeof globalThis} The detected global object.\n */\nexport const detectGlobalObject = (): typeof globalThis => {\n if (typeof globalThis !== \"undefined\") return globalThis;\n if (typeof window !== \"undefined\") return window;\n if (typeof global !== \"undefined\") return global;\n if (typeof self !== \"undefined\") return self;\n throw new Error(\"Unable to locate global object\");\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","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Normalizes various GraphQL operation type representations to a standard form.\n * @param type The operation type to normalize\n * @returns The normalized operation type or null if not provided\n */\nexport const normalizeOperationType = (\n type?: GraphqlOprtation | \"query\" | \"mutation\" | \"subscription\" | null,\n): GraphqlOprtation | null => {\n if (!type) return null;\n if (type === \"query\") return GraphqlOprtation.QUERY;\n if (type === \"mutation\") return GraphqlOprtation.MUTATION;\n if (type === \"subscription\") return GraphqlOprtation.SUB;\n\n return type;\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 WebSocket URL for Limelight web app connections.\n */\nexport const LIMELIGHT_WEB_WSS_URL = \"wss://api.getlimelight.io\";\n\n/**\n * The WebSocket URL for Limelight desktop app connections.\n */\nexport const LIMELIGHT_DESKTOP_WSS_URL = \"ws://localhost:8484\";\n\n/**\n * The WebSocket URL for Limelight MCP server connections.\n */\nexport const LIMELIGHT_MCP_WS_URL = \"ws://localhost:9229\";\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\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\n/**\n * Commonly used HTTP header names that are considered sensitive and should be redacted in Limelight messages.\n */\nexport const BINARY_CONTENT_TYPES = [\n \"image/\",\n \"audio/\",\n \"video/\",\n \"application/octet-stream\",\n \"application/pdf\",\n \"application/zip\",\n \"application/gzip\",\n];\n\n/**\n * Max body size for capture in Limelight. Requests or responses with bodies larger than this will have their body content truncated to avoid excessive memory usage.\n */\nexport const MAX_BODY_SIZE = 1024 * 1024; // 1MB cap for body capture\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, string>();\n\n const process = (val: unknown, currentDepth: number, path: string): 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 `[Symbol: ${val.description || \"\"}]`;\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 const seenPath = seen.get(val);\n\n if (seenPath !== undefined) {\n return `[Circular → ${seenPath}]`;\n }\n\n seen.set(val, path || \"root\");\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n ...Object.fromEntries(\n Object.entries(val).filter(\n ([k]) => ![\"name\", \"message\", \"stack\"].includes(k),\n ),\n ),\n };\n }\n\n if (val instanceof Date) {\n return { __type: \"Date\", value: val.toISOString() };\n }\n\n if (val instanceof RegExp) {\n return { __type: \"RegExp\", value: val.toString() };\n }\n\n if (val instanceof Map) {\n return {\n __type: \"Map\",\n size: val.size,\n entries: Array.from(val.entries()).map(([k, v], i) => [\n process(k, currentDepth + 1, `${path}.Map[${i}].key`),\n process(v, currentDepth + 1, `${path}.Map[${i}].value`),\n ]),\n };\n }\n\n if (val instanceof Set) {\n return {\n __type: \"Set\",\n size: val.size,\n values: Array.from(val).map((v, i) =>\n process(v, currentDepth + 1, `${path}.Set[${i}]`),\n ),\n };\n }\n\n if (val instanceof WeakMap) {\n return { __type: \"WeakMap\", note: \"[Contents not enumerable]\" };\n }\n if (val instanceof WeakSet) {\n return { __type: \"WeakSet\", note: \"[Contents not enumerable]\" };\n }\n\n if (val instanceof Promise) {\n return { __type: \"Promise\", note: \"[Pending state not accessible]\" };\n }\n\n if (val instanceof ArrayBuffer) {\n return { __type: \"ArrayBuffer\", byteLength: val.byteLength };\n }\n\n if (ArrayBuffer.isView(val)) {\n const typedArray = val as any;\n return {\n __type: val.constructor.name,\n length: typedArray.length ?? typedArray.byteLength,\n preview:\n typedArray.length <= 10\n ? Array.from(typedArray.slice?.(0, 10) ?? [])\n : `[${typedArray.length} items]`,\n };\n }\n\n if (typeof URL !== \"undefined\" && val instanceof URL) {\n return { __type: \"URL\", href: val.href };\n }\n\n if (\n typeof URLSearchParams !== \"undefined\" &&\n val instanceof URLSearchParams\n ) {\n return {\n __type: \"URLSearchParams\",\n entries: Object.fromEntries(val.entries()),\n };\n }\n\n if (\n val &&\n typeof (val as any).$$typeof === \"symbol\" &&\n String((val as any).$$typeof).includes(\"react.element\")\n ) {\n return {\n __type: \"ReactElement\",\n type:\n typeof (val as any).type === \"function\"\n ? (val as any).type.name || \"Component\"\n : (val as any).type || \"unknown\",\n key: (val as any).key,\n };\n }\n\n if (Array.isArray(val)) {\n return val.map((item, i) =>\n process(item, currentDepth + 1, `${path}[${i}]`),\n );\n }\n\n const result: Record<string, any> = {};\n const proto = Object.getPrototypeOf(val);\n\n if (proto && proto.constructor && proto.constructor.name !== \"Object\") {\n result.__type = proto.constructor.name;\n }\n\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n try {\n result[key] = process(\n (val as any)[key],\n currentDepth + 1,\n `${path}.${key}`,\n );\n } catch (e) {\n result[key] =\n `[Error accessing property: ${e instanceof Error ? e.message : String(e)}]`;\n }\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0, \"root\");\n return JSON.stringify(processed, null, pretty ? 2 : undefined);\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","/**\n * Returns true if DOM APIs are available (window + document).\n * True in browsers, false in Node.js and React Native.\n */\nexport const hasDOM = (): boolean =>\n typeof window !== \"undefined\" && typeof document !== \"undefined\";\n\n/**\n * Returns true if running on a Node.js server (not browser, not React Native).\n */\nexport const isServer = (): boolean =>\n !hasDOM() &&\n typeof process !== \"undefined\" &&\n typeof process.versions !== \"undefined\" &&\n typeof process.versions.node !== \"undefined\";\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 type http from \"http\";\n\n/**\n * Resolves the full URL from the given HTTP request options.\n *\n * @param protocol The protocol to use (e.g. \"http:\" or \"https:\")\n * @param options The HTTP request options containing host, port, and path\n * @returns The fully resolved URL as a string\n */\nexport const resolveUrl = (\n protocol: string,\n options: http.RequestOptions,\n): string => {\n const host = options.hostname || options.host || \"localhost\";\n const port = options.port ? `:${options.port}` : \"\";\n const path = options.path || \"/\";\n return `${protocol}//${host}${port}${path}`;\n};\n","import { BINARY_CONTENT_TYPES } from \"@/constants\";\n\n/**\n * Checks if a given content type is considered binary.\n * @param {string} contentType - The content type to check.\n * @returns {boolean} True if the content type is binary, false otherwise.\n */\nexport const isBinaryContentType = (contentType: string): boolean => {\n return BINARY_CONTENT_TYPES.some((type) =>\n contentType.toLowerCase().includes(type),\n );\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n }\n\n return;\n }\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 // always log an error if beforeSend returns wrong type\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n }\n\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","export interface TraceStore {\n traceId: string;\n}\n\ninterface TraceContextLike {\n getStore(): TraceStore | undefined;\n run<T>(store: TraceStore, callback: (...args: any[]) => T, ...args: any[]): T;\n}\n\nlet _resolved = false;\nlet _traceContext: TraceContextLike | undefined;\n\n/**\n * Returns the AsyncLocalStorage-backed trace context if available (Node.js only).\n * Returns undefined in browser environments where AsyncLocalStorage is not available.\n *\n * @returns {TraceContextLike | undefined} The trace context or undefined if not available.\n */\nexport const getTraceContext = (): TraceContextLike | undefined => {\n if (!_resolved) {\n _resolved = true;\n try {\n // Use indirect require via globalThis so Metro/webpack can't\n // statically resolve and bundle this Node-only module.\n const _require = globalThis[\"require\"] as typeof require;\n const { AsyncLocalStorage } = _require(\"node:async_hooks\");\n\n _traceContext = new AsyncLocalStorage() as TraceContextLike;\n } catch {\n // Browser / React Native — AsyncLocalStorage not available\n }\n }\n\n return _traceContext;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n detectGlobalObject,\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch | undefined;\n\n private config: LimelightConfig | null = null;\n private isSetup = false;\n private globalObject: typeof globalThis;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {\n this.globalObject = detectGlobalObject();\n if (typeof this.globalObject.fetch === \"function\") {\n this.originalFetch = this.globalObject.fetch.bind(this.globalObject);\n }\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n }\n\n return;\n }\n\n if (!this.originalFetch) {\n if (config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] fetch is not available in this environment, skipping network interception\",\n );\n }\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const originalFetch = this.originalFetch;\n\n this.globalObject.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 const traceHeaderName =\n self.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n\n if (!headers[traceHeaderName]) {\n const existingTraceId = getTraceContext()?.getStore()?.traceId;\n headers[traceHeaderName] = existingTraceId || generateRequestId();\n }\n\n const traceId = headers[traceHeaderName];\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\n if (self.config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Failed to read request body from Request object\",\n );\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 const rawBody = requestBody?.raw;\n\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\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 originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n // always log an error if beforeSend returns wrong type\n console.error(\"[Limelight] beforeSend must return same event type\");\n return originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await 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 traceId,\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 // always log an error if beforeSend returns wrong type\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 isAbort =\n err instanceof Error &&\n (err.name === \"AbortError\" || err.message.includes(\"aborted\"));\n\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 traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: isAbort ? NetworkPhase.ABORT : NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: isAbort ? \"Request aborted\" : errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n }\n\n return;\n }\n\n this.isSetup = false;\n if (this.originalFetch) {\n this.globalObject.fetch = this.originalFetch;\n }\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 traceId?: 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 if (typeof XMLHttpRequest !== \"undefined\") {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\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 (typeof XMLHttpRequest === \"undefined\") {\n return;\n }\n\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n }\n\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 traceHeaderName =\n self.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n\n if (!data.headers[traceHeaderName]) {\n data.traceId = generateRequestId();\n self.originalXHRSetRequestHeader.call(\n this,\n traceHeaderName,\n data.traceId,\n );\n } else {\n data.traceId = data.headers[traceHeaderName];\n }\n\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture,\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n traceId: data.traceId,\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 // always log an error if beforeSend returns wrong type\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 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\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\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 traceId: data.traceId,\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 //always log an error if beforeSend returns wrong type\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 = (\n errorMessage: string,\n phase: NetworkPhase.ERROR | NetworkPhase.ABORT = NetworkPhase.ERROR,\n ) => {\n if (responseSent) return;\n\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n traceId: data.traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: phase,\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\", NetworkPhase.ABORT);\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 return;\n }\n this.isSetup = false;\n\n if (typeof XMLHttpRequest !== \"undefined\") {\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n }\n}\n","import type http from \"http\";\nimport type https from \"https\";\nimport {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isBinaryContentType,\n redactSensitiveHeaders,\n resolveUrl,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\nimport { MAX_BODY_SIZE } from \"@/constants\";\n\nexport class HttpInterceptor {\n private originalHttpRequest: typeof http.request | null = null;\n private originalHttpGet: typeof http.get | null = null;\n private originalHttpsRequest: typeof https.request | null = null;\n private originalHttpsGet: typeof https.get | null = null;\n\n private httpModule: typeof http | null = null;\n private httpsModule: typeof https | null = null;\n\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 try {\n const _require = globalThis[\"require\"] as typeof require;\n this.httpModule = _require(\"http\");\n this.httpsModule = _require(\"https\");\n\n this.originalHttpRequest = this.httpModule!.request;\n this.originalHttpGet = this.httpModule!.get;\n this.originalHttpsRequest = this.httpsModule!.request;\n this.originalHttpsGet = this.httpsModule!.get;\n } catch {\n // Browser / React Native - http module not available\n }\n }\n\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] HTTP interceptor already set up\");\n }\n\n return;\n }\n\n if (!this.httpModule || !this.httpsModule) {\n if (config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Node http module not available, skipping HTTP interception\",\n );\n }\n\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const httpMod = this.httpModule;\n const httpsMod = this.httpsModule;\n\n httpMod.request = (...args: any[]) => {\n return self.interceptRequest(\n \"http:\",\n self.originalHttpRequest!,\n httpMod,\n args,\n );\n };\n\n httpMod.get = (...args: any[]) => {\n const req = self.interceptRequest(\n \"http:\",\n self.originalHttpRequest!,\n httpMod,\n args,\n );\n req.end();\n return req;\n };\n\n httpsMod.request = (...args: any[]) => {\n return self.interceptRequest(\n \"https:\",\n self.originalHttpsRequest!,\n httpsMod,\n args,\n );\n };\n\n httpsMod.get = (...args: any[]) => {\n const req = self.interceptRequest(\n \"https:\",\n self.originalHttpsRequest!,\n httpsMod,\n args,\n );\n req.end();\n return req;\n };\n }\n\n private interceptRequest(\n protocol: string,\n originalMethod: typeof http.request,\n module: typeof http | typeof https,\n args: any[],\n ): http.ClientRequest {\n let url: string | URL | undefined;\n let options: http.RequestOptions;\n let callback: ((res: http.IncomingMessage) => void) | undefined;\n\n if (typeof args[0] === \"string\" || args[0] instanceof URL) {\n url = args[0];\n\n if (typeof args[1] === \"function\") {\n options = {};\n callback = args[1];\n } else {\n options = args[1] || {};\n callback = args[2];\n }\n } else {\n options = args[0] || {};\n callback = args[1];\n }\n\n let resolvedUrl: string;\n\n if (url) {\n resolvedUrl = url.toString();\n } else {\n resolvedUrl = resolveUrl(protocol, options);\n }\n\n const limelightServerUrl = this.config?.serverUrl || \"\";\n\n if (limelightServerUrl && resolvedUrl.includes(limelightServerUrl)) {\n return originalMethod.apply(module, args as any);\n }\n\n const self = this;\n const requestId = generateRequestId();\n const startTime = Date.now();\n const initiator = getInitiator();\n\n const traceHeaderName =\n this.config?.traceHeaderName ?? \"x-limelight-trace-id\";\n const existingTraceId = getTraceContext()?.getStore()?.traceId;\n const traceId = existingTraceId || generateRequestId();\n\n if (!options.headers) {\n options.headers = {};\n }\n\n (options.headers as Record<string, string>)[traceHeaderName] = traceId;\n\n const method = (options.method || \"GET\").toUpperCase() as HttpMethod;\n\n let patchedArgs: any[];\n\n if (url) {\n patchedArgs = callback ? [url, options, callback] : [url, options];\n } else {\n patchedArgs = callback ? [options, callback] : [options];\n }\n\n const req: http.ClientRequest = originalMethod.apply(\n module,\n patchedArgs as any,\n );\n\n const bodyChunks: Buffer[] = [];\n let totalBodySize = 0;\n let requestEventSent = false;\n const originalWrite = req.write.bind(req);\n const originalEnd = req.end.bind(req);\n\n req.write = (\n chunk: any,\n encodingOrCallback?: BufferEncoding | ((error?: Error | null) => void),\n callback?: (error?: Error | null) => void,\n ): boolean => {\n if (chunk && totalBodySize < MAX_BODY_SIZE) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bodyChunks.push(buf);\n totalBodySize += buf.length;\n }\n return originalWrite(chunk, encodingOrCallback as any, callback as any);\n };\n\n req.end = (\n chunk?: any,\n encodingOrCallback?: BufferEncoding | (() => void),\n callback?: () => void,\n ): http.ClientRequest => {\n if (\n chunk &&\n typeof chunk !== \"function\" &&\n totalBodySize < MAX_BODY_SIZE\n ) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n bodyChunks.push(buf);\n totalBodySize += buf.length;\n }\n\n if (!requestEventSent) {\n requestEventSent = true;\n\n const fullBody =\n bodyChunks.length > 0\n ? Buffer.concat(bodyChunks).toString(\"utf-8\")\n : undefined;\n\n const headers: Record<string, string> = {};\n const rawHeaders = req.getHeaders();\n\n for (const [key, value] of Object.entries(rawHeaders)) {\n if (value !== undefined) {\n headers[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n }\n }\n\n const requestBody = serializeBody(\n fullBody,\n self.config?.disableBodyCapture,\n );\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.HTTP,\n url: resolvedUrl,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(resolvedUrl),\n initiator,\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 originalEnd(\n chunk,\n encodingOrCallback as any,\n callback as any,\n );\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return originalEnd(\n chunk,\n encodingOrCallback as any,\n callback as any,\n );\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n }\n\n return originalEnd(chunk, encodingOrCallback as any, callback as any);\n };\n\n let responseSent = false;\n\n req.on(\"response\", (res: http.IncomingMessage) => {\n const responseChunks: Buffer[] = [];\n let responseSize = 0;\n\n res.on(\"data\", (chunk: Buffer | string) => {\n if (responseSize < MAX_BODY_SIZE) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n responseChunks.push(buf);\n responseSize += buf.length;\n }\n });\n\n res.on(\"end\", () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const responseHeaders: Record<string, string> = {};\n\n if (res.headers) {\n for (const [key, value] of Object.entries(res.headers)) {\n if (value) {\n responseHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n }\n }\n\n const contentType = responseHeaders[\"content-type\"] || \"\";\n let responseBodyStr: string | undefined;\n\n if (responseChunks.length > 0) {\n if (isBinaryContentType(contentType)) {\n responseBodyStr = `[Binary Data: ${contentType}]`;\n } else {\n const full = Buffer.concat(responseChunks);\n responseBodyStr =\n full.length > MAX_BODY_SIZE\n ? full.toString(\"utf-8\", 0, MAX_BODY_SIZE) + \"...[truncated]\"\n : full.toString(\"utf-8\");\n }\n }\n\n const responseBody = serializeBody(\n responseBodyStr,\n self.config?.disableBodyCapture,\n );\n\n const statusCode = res.statusCode ?? 0;\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.HTTP,\n status: statusCode,\n statusText: res.statusMessage || \"\",\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: statusCode >= 200 && statusCode < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) return;\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n });\n });\n\n req.on(\"error\", (err: Error) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.HTTP,\n errorMessage: err.message || \"Network request failed\",\n stack: err.stack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n req.on(\"timeout\", () => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.HTTP,\n errorMessage: \"Request timeout\",\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n req.on(\"close\", () => {\n if (responseSent) return;\n if (!req.destroyed) return;\n\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n traceId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ABORT,\n networkType: NetworkType.HTTP,\n errorMessage: \"Request aborted\",\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n if (\n modifiedEvent &&\n (modifiedEvent.phase === NetworkPhase.ERROR ||\n modifiedEvent.phase === NetworkPhase.ABORT)\n ) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n });\n\n return req;\n }\n\n cleanup() {\n if (!this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] HTTP interceptor not set up\");\n }\n return;\n }\n\n this.isSetup = false;\n\n if (this.httpModule && this.originalHttpRequest) {\n this.httpModule.request = this.originalHttpRequest;\n }\n\n if (this.httpModule && this.originalHttpGet) {\n this.httpModule.get = this.originalHttpGet;\n }\n\n if (this.httpsModule && this.originalHttpsRequest) {\n this.httpsModule.request = this.originalHttpsRequest;\n }\n\n if (this.httpsModule && this.originalHttpsGet) {\n this.httpsModule.get = this.originalHttpsGet;\n }\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} 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 if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Render interceptor already set up\");\n }\n\n return;\n }\n\n this.config = config;\n\n if (!this.installHook()) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Failed to install render hook\");\n }\n\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 /**\n * Installs or wraps the React DevTools global hook.\n * Returns true if successful, false otherwise.\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 /**\n * Wraps an existing React DevTools hook to intercept render events.\n * Preserves original functionality.\n * @param hook - The existing React DevTools hook\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 /**\n * Creates a new React DevTools hook to intercept render events.\n * @param globalObj - The global object (window or global)\n * @param hookKey - The key for the React DevTools hook\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 * @param rendererID - The renderer ID\n * @param root - The fiber root\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 (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Error processing fiber tree:\", error);\n }\n }\n }\n\n /**\n * First pass: count rendered components for cost distribution.\n * @param fiber - The current fiber node\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 /**\n * Handles a fiber unmount - marks component as unmounted.\n * @param rendererID - The renderer ID\n * @param fiber - The fiber being unmounted\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 * @param fiber - The current fiber node\n * @param parentComponentId - The parent component ID\n * @param depth - The current depth in the tree\n */\n private walkFiberTree(\n fiber: MinimalFiber | null,\n parentComponentId: string | null,\n depth: number,\n ): void {\n if (!fiber) return;\n\n let currentParentId = parentComponentId;\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 currentParentId = componentId;\n }\n\n this.walkFiberTree(fiber.child, currentParentId, 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 * @param fiber - The current fiber node\n * @param componentId - The component ID\n * @param parentComponentId - The parent component ID\n * @param depth - The current depth in the tree\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 * Accumulate prop change details into the profile.\n * @param profile - The component profile\n * @param changes - The list of prop change details\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 * @param profile - The component profile\n * @returns The prop change snapshot or undefined\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 /**\n * Updates the suspicious flag based on render velocity and count.\n * @param profile - The component profile\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 * @param profile - The component profile\n * @returns The calculated velocity\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 * Only emits profiles that have significant changes since last emit.\n * Also emits unmounts.\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 * Infers the cause of the render by comparing current and previous fiber states.\n * @param fiber - The current fiber node\n * @param parentComponentId - The parent component ID\n * @returns The inferred render cause\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 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 * @param prevProps - The previous props\n * @param nextProps - The next props\n * @returns List of prop change details\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 * @param a - The first value\n * @param b - The second value\n * @returns True if shallow equal, false otherwise\n */\n private isShallowEqual(a: any, b: any): boolean {\n if (a === b) return true;\n\n if (typeof a !== typeof b) return false;\n\n if (a === null || b === null) return false;\n\n if (typeof a === \"function\" && typeof b === \"function\") {\n return true;\n }\n\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 /**\n * Determines if a fiber represents a user-defined component.\n * @param fiber - The fiber node\n * @returns True if user component, false otherwise\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 /**\n * Determines if a fiber performed work during the commit.\n * @param fiber - The fiber node\n * @returns True if performed work, false otherwise\n */\n private didFiberRender(fiber: MinimalFiber): boolean {\n return (fiber.flags & FiberFlags.PerformedWork) !== 0;\n }\n\n /**\n * Gets or creates a unique component ID for a fiber.\n * @param fiber - The fiber node\n * @returns The unique component ID\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 /**\n * Gets the display name of a component from a fiber.\n * @param fiber - The fiber node\n * @returns The component name\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 /**\n * Gets the component type from a fiber.\n * @param fiber - The fiber node\n * @returns The component type\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 /**\n * Cleans up and restores original hook behavior.\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 /**\n * Resets all collected profiles\n */\n resetProfiles(): void {\n this.profiles.clear();\n this.fiberToComponentId = new WeakMap<MinimalFiber, string>();\n this.pendingUnmounts = [];\n this.currentCommitComponents.clear();\n this.componentIdCounter = 0;\n }\n}\n","import { safeStringify } from \"@/helpers\";\nimport {\n ConsoleLevel,\n ConsoleSource,\n ConsoleType,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\n/**\n * Captures uncaught exceptions and unhandled promise rejections in Node.js\n * and sends them as CONSOLE error events through the Limelight protocol.\n *\n * Only activates in server environments where `process` is available.\n */\nexport class ErrorInterceptor {\n private isSetup = false;\n private config: LimelightConfig | null = null;\n private counter = 0;\n\n private uncaughtExceptionHandler: ((error: Error) => void) | null = null;\n private unhandledRejectionHandler:\n | ((reason: unknown, promise: Promise<unknown>) => void)\n | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {}\n\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Error interceptor already set up\");\n }\n return;\n }\n\n if (typeof process === \"undefined\" || !process.on) {\n return;\n }\n\n this.isSetup = true;\n this.config = config;\n\n this.uncaughtExceptionHandler = (error: Error) => {\n this.sendErrorEvent(error, \"uncaughtException\");\n // Give the WebSocket time to actually send the error event over the wire\n // before exiting. 200ms is enough for a local/LAN WebSocket flush.\n setTimeout(() => {\n process.exit(1);\n }, 200);\n };\n\n this.unhandledRejectionHandler = (reason: unknown) => {\n const error =\n reason instanceof Error ? reason : new Error(String(reason));\n this.sendErrorEvent(error, \"unhandledRejection\");\n };\n\n process.on(\"uncaughtException\", this.uncaughtExceptionHandler);\n process.on(\"unhandledRejection\", this.unhandledRejectionHandler);\n }\n\n cleanup() {\n if (!this.isSetup) return;\n\n this.isSetup = false;\n\n if (this.uncaughtExceptionHandler) {\n process.removeListener(\n \"uncaughtException\",\n this.uncaughtExceptionHandler,\n );\n this.uncaughtExceptionHandler = null;\n }\n\n if (this.unhandledRejectionHandler) {\n process.removeListener(\n \"unhandledRejection\",\n this.unhandledRejectionHandler,\n );\n this.unhandledRejectionHandler = null;\n }\n\n this.config = null;\n }\n\n private sendErrorEvent(error: Error, source: string) {\n const sessionId = this.getSessionId();\n\n const event: LimelightMessage = {\n id: `${sessionId}-${Date.now()}-${this.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: ConsoleLevel.ERROR,\n timestamp: Date.now(),\n sessionId,\n source: ConsoleSource.APP,\n consoleType: ConsoleType.EXCEPTION,\n args: [safeStringify(`[${source}] ${error.message}`)],\n stackTrace: error.stack,\n };\n\n if (this.config?.beforeSend) {\n const modified = this.config.beforeSend(event);\n\n if (!modified) return;\n }\n\n this.sendMessage(event);\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n StateLibrary,\n StatePhase,\n StateInitEvent,\n StateUpdateEvent,\n StateAction,\n} from \"@/types/state\";\n\ninterface RegisteredStore {\n name: string;\n library: StateLibrary;\n unsubscribe: () => void;\n}\n\nexport class StateInterceptor {\n private sendMessage: (message: LimelightMessage) => void;\n private getSessionId: () => string;\n\n private stores: Map<string, RegisteredStore> = new Map();\n private config: LimelightConfig | null = null;\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 this.config = config;\n\n if (!config.stores) return;\n if (config.enableStateInspector === false) return;\n\n for (const [name, store] of Object.entries(config.stores)) {\n this.registerStore(name, store);\n }\n }\n\n /**\n * Register a store for inspection.\n * Can be called manually via Limelight.addStore() for dynamic registration.\n */\n registerStore(name: string, store: unknown): void {\n if (this.stores.has(name)) {\n if (this.config?.enableInternalLogging) {\n console.warn(`[Limelight] Store \"${name}\" already registered`);\n }\n\n return;\n }\n\n const library = this.detectLibrary(store);\n\n if (!library) {\n //always log warning if store type cannot be detected\n console.warn(\n `[Limelight] Could not detect store type for \"${name}\". Expected Zustand or Redux store.`,\n );\n return;\n }\n\n const state = this.getState(store);\n\n const initEvent: StateInitEvent = {\n phase: StatePhase.INIT,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: name,\n library,\n state,\n },\n };\n\n this.emitEvent(initEvent);\n\n const unsubscribe = this.subscribe(store, library, name);\n\n this.stores.set(name, { name, library, unsubscribe });\n }\n\n /**\n * Unregister a store and stop listening to changes.\n * Can be called manually via Limelight.removeStore().\n * @param name The name of the store to unregister\n */\n unregisterStore(name: string): void {\n const store = this.stores.get(name);\n if (store) {\n store.unsubscribe();\n this.stores.delete(name);\n }\n }\n\n /**\n * Emit an event, applying beforeSend hook if configured\n * @param event The event to emit\n */\n private emitEvent(event: StateInitEvent | StateUpdateEvent): void {\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(event);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (\n modifiedEvent.phase !== StatePhase.INIT &&\n modifiedEvent.phase !== StatePhase.UPDATE\n ) {\n // always log an error if beforeSend returns wrong type\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n this.sendMessage(modifiedEvent);\n } else {\n this.sendMessage(event);\n }\n }\n\n /**\n * Detect whether a store is Zustand or Redux\n * @param store The store to inspect\n * @return StateLibrary or null if unknown\n */\n private detectLibrary(store: unknown): StateLibrary | null {\n if (!store || (typeof store !== \"function\" && typeof store !== \"object\")) {\n return null;\n }\n\n // Redux stores have dispatch, getState, subscribe, and replaceReducer\n if (\n typeof store === \"object\" &&\n \"dispatch\" in store &&\n \"getState\" in store &&\n \"subscribe\" in store &&\n typeof (store as any).dispatch === \"function\"\n ) {\n return StateLibrary.REDUX;\n }\n\n // Zustand stores are functions with getState and subscribe\n if (\n typeof store === \"function\" &&\n \"getState\" in store &&\n \"subscribe\" in store &&\n typeof (store as any).getState === \"function\"\n ) {\n return StateLibrary.ZUSTAND;\n }\n\n // Vanilla Zustand stores (created with createStore instead of create)\n if (\n typeof store === \"object\" &&\n \"getState\" in store &&\n \"setState\" in store &&\n \"subscribe\" in store &&\n !(\"dispatch\" in store)\n ) {\n return StateLibrary.ZUSTAND;\n }\n\n return null;\n }\n\n /**\n * Get current state from a store\n * @param store The store to get state from\n * @return The current state\n */\n private getState(store: unknown): unknown {\n const storeAny = store as any;\n return storeAny.getState();\n }\n\n /**\n * Subscribe to store changes\n * @param store The store to subscribe to\n * @param library The detected state library\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribe(\n store: unknown,\n library: StateLibrary,\n storeName: string,\n ): () => void {\n const storeAny = store as any;\n\n if (library === StateLibrary.ZUSTAND) {\n return this.subscribeZustand(storeAny, storeName);\n } else {\n return this.subscribeRedux(storeAny, storeName);\n }\n }\n\n /**\n * Subscribe to Zustand store changes\n * @param store The Zustand store\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribeZustand(store: any, storeName: string): () => void {\n return store.subscribe((state: unknown, prevState: unknown) => {\n const action = this.inferZustandAction(state, prevState);\n const stackTrace = this.captureStackTrace();\n\n const updateEvent: StateUpdateEvent = {\n phase: StatePhase.UPDATE,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: storeName,\n library: StateLibrary.ZUSTAND,\n state,\n action,\n stackTrace,\n },\n };\n\n this.emitEvent(updateEvent);\n });\n }\n\n /**\n * Subscribe to Redux store changes\n * @param store The Redux store\n * @param storeName The name of the store\n * @return Unsubscribe function\n */\n private subscribeRedux(store: any, storeName: string): () => void {\n let lastAction: StateAction = { type: \"@@INIT\" };\n\n const originalDispatch = store.dispatch;\n store.dispatch = (action: any) => {\n lastAction = {\n type: action?.type || \"unknown\",\n payload: action?.payload,\n };\n return originalDispatch(action);\n };\n\n const unsubscribe = store.subscribe(() => {\n const newState = store.getState();\n const stackTrace = this.captureStackTrace();\n\n const updateEvent: StateUpdateEvent = {\n phase: StatePhase.UPDATE,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n data: {\n storeId: storeName,\n library: StateLibrary.REDUX,\n state: newState,\n action: lastAction,\n stackTrace,\n },\n };\n\n this.emitEvent(updateEvent);\n });\n\n return () => {\n unsubscribe();\n store.dispatch = originalDispatch;\n };\n }\n\n /**\n * Infer action name from stack trace for Zustand\n * @param state The new state\n * @param prevState The previous state\n * @return Inferred StateAction\n */\n private inferZustandAction(state: unknown, prevState: unknown): StateAction {\n const actionType = this.parseActionFromStack(this.captureStackTrace());\n const payload = this.computePartialState(state, prevState);\n\n return {\n type: actionType,\n payload,\n };\n }\n\n /**\n * Parse function name from stack trace\n * @param stack The stack trace string\n * @return The inferred action name\n */\n private parseActionFromStack(stack?: string): string {\n if (!stack) return \"set\";\n\n const lines = stack.split(\"\\n\");\n\n for (const line of lines) {\n if (line.includes(\"node_modules/zustand\")) continue;\n if (line.includes(\"node_modules/immer\")) continue;\n if (line.includes(\"StateInterceptor\")) continue;\n if (line.includes(\"limelight\")) continue;\n\n // V8 format\n const v8Match =\n line.match(/at\\s+(?:Object\\.)?(\\w+)\\s+\\(/) ||\n line.match(/at\\s+(\\w+)\\s*\\[/) ||\n line.match(/at\\s+(\\w+)/);\n\n // Hermes format\n const hermesMatch = line.match(/^(\\w+)@/);\n\n const match = v8Match || hermesMatch;\n\n if (match && match[1]) {\n const name = match[1];\n if (\n ![\n \"anonymous\",\n \"Object\",\n \"Array\",\n \"Function\",\n \"eval\",\n \"Error\",\n ].includes(name)\n ) {\n return name;\n }\n }\n }\n\n return \"set\";\n }\n\n /**\n * Compute what keys changed between states (shallow)\n * @param state The new state\n * @param prevState The previous state\n * @return Partial state with only changed keys\n */\n private computePartialState(state: unknown, prevState: unknown): unknown {\n if (\n typeof state !== \"object\" ||\n state === null ||\n typeof prevState !== \"object\" ||\n prevState === null\n ) {\n return state;\n }\n\n const partial: Record<string, unknown> = {};\n const stateObj = state as Record<string, unknown>;\n const prevObj = prevState as Record<string, unknown>;\n\n for (const key of Object.keys(stateObj)) {\n if (stateObj[key] !== prevObj[key]) {\n partial[key] = stateObj[key];\n }\n }\n\n if (Object.keys(partial).length === 0) {\n return state;\n }\n\n return partial;\n }\n\n /**\n * Capture current stack trace\n */\n private captureStackTrace(): string | undefined {\n try {\n const err = new Error();\n return err.stack;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Cleanup all subscriptions\n */\n cleanup(): void {\n for (const [, store] of this.stores) {\n store.unsubscribe();\n }\n this.stores.clear();\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n NetworkPhase,\n NetworkType,\n NetworkRequest,\n NetworkResponse,\n NetworkErrorEvent,\n HttpMethod,\n} from \"@/types\";\nimport {\n serializeBody,\n redactSensitiveHeaders,\n formatRequestName,\n normalizeOperationType,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport {\n RequestBridgeConfig,\n ResponseBridgeConfig,\n} from \"@/types/request-bridge\";\n\ninterface PendingRequest {\n startTime: number;\n config: RequestBridgeConfig;\n}\n\nexport class RequestBridge {\n private pendingRequests = new Map<string, PendingRequest>();\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string,\n ) {\n // No-op\n }\n\n /**\n * Updates the config reference (called when LimelightClient configures)\n * @param config The new Limelight configuration or null to disable\n */\n setConfig(config: LimelightConfig | null) {\n this.config = config;\n }\n\n /**\n * Starts tracking a manual request. Returns a requestId to use with endRequest/failRequest.\n * @param config The request configuration\n * @returns The generated request ID\n */\n startRequest(config: RequestBridgeConfig): string {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n this.pendingRequests.set(requestId, { startTime, config });\n\n let bodyToSerialize = config.body;\n\n if (config.graphql && !config.body) {\n bodyToSerialize = JSON.stringify({\n operationName: config.graphql.operationName,\n variables: config.graphql.variables,\n query: config.graphql.query,\n });\n }\n\n const method = (config.method?.toUpperCase() || \"POST\") as HttpMethod;\n const headers = config.headers || {};\n\n const requestBody = serializeBody(\n typeof bodyToSerialize === \"string\"\n ? bodyToSerialize\n : JSON.stringify(bodyToSerialize),\n this.config?.disableBodyCapture,\n );\n\n let requestEvent: NetworkRequest = {\n id: requestId,\n sessionId: this.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url: config.url,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: config.name || formatRequestName(config.url),\n initiator: \"manual\",\n requestSize: requestBody?.size ?? 0,\n graphql: config.graphql\n ? {\n operationName: config.graphql.operationName,\n operationType: normalizeOperationType(config.graphql.operationType),\n variables: config.graphql.variables,\n query: config.graphql.query,\n }\n : undefined,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n this.pendingRequests.delete(requestId);\n return requestId;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return requestId;\n }\n\n requestEvent = modifiedEvent as NetworkRequest;\n }\n\n this.sendMessage(requestEvent);\n\n return requestId;\n }\n\n /**\n * Completes a tracked request with a successful response.\n * @param requestId The ID returned from startRequest\n * @param response The response data\n */\n endRequest(requestId: string, response: ResponseBridgeConfig): void {\n const pending = this.pendingRequests.get(requestId);\n\n if (!pending) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n `[Limelight] No pending request found for id: ${requestId}`,\n );\n }\n return;\n }\n\n this.pendingRequests.delete(requestId);\n\n const endTime = Date.now();\n const duration = endTime - pending.startTime;\n\n const responseHeaders = response.headers || {};\n const responseBody = serializeBody(\n typeof response.body === \"string\"\n ? response.body\n : JSON.stringify(response.body),\n this.config?.disableBodyCapture,\n );\n\n let responseEvent: NetworkResponse = {\n id: requestId,\n sessionId: this.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: false,\n ok: response.status >= 200 && response.status < 300,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modifiedEvent as NetworkResponse;\n }\n\n this.sendMessage(responseEvent);\n }\n\n /**\n * Completes a tracked request with an error.\n * @param requestId The ID returned from startRequest\n * @param error The error object or message\n */\n failRequest(requestId: string, error: unknown): void {\n const pending = this.pendingRequests.get(requestId);\n\n if (!pending) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n `[Limelight] No pending request found for id: ${requestId}`,\n );\n }\n return;\n }\n\n this.pendingRequests.delete(requestId);\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: this.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage,\n stack: errorStack,\n };\n\n if (this.config?.beforeSend) {\n const modifiedEvent = this.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent as NetworkErrorEvent;\n }\n }\n\n this.sendMessage(errorEvent);\n }\n\n /**\n * Cleans up any pending requests (called on disconnect)\n */\n cleanup() {\n this.pendingRequests.clear();\n }\n}\n","// limelight/CommandHandler.ts\nimport { Command, CommandType, LimelightMessage } from \"@/types\";\nimport { RenderInterceptor } from \"../interceptors\";\n\nexport class CommandHandler {\n constructor(\n private interceptors: {\n render: RenderInterceptor;\n },\n private sendMessage: (message: LimelightMessage) => void,\n private getConfig: () => { enableInternalLogging?: boolean } | null,\n ) {\n // No-op\n }\n\n /**\n * Handles an incoming command.\n * @param command - The command to handle\n */\n handle(command: Command): void {\n const config = this.getConfig();\n\n if (config?.enableInternalLogging) {\n console.log(\"[Limelight] Received command:\", command.type);\n }\n\n switch (command.type) {\n case CommandType.CLEAR_RENDERS:\n this.interceptors.render.resetProfiles();\n break;\n\n default:\n if (config?.enableInternalLogging) {\n console.warn(\"[Limelight] Unknown command:\", command.type);\n }\n }\n\n if (command.id) {\n this.sendMessage({\n phase: CommandType.ACK,\n commandId: command.id,\n type: command.type,\n success: true,\n });\n }\n }\n}\n","import type { IncomingMessage, ServerResponse } from \"http\";\nimport {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport { redactSensitiveHeaders, serializeBody } from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\nimport { getTraceContext } from \"@/limelight/context\";\n\nconst DEFAULT_MAX_BODY_SIZE = 64 * 1024; // 64KB\n\nexport interface MiddlewareOptions {\n /** Maximum body size to capture in bytes. Bodies larger than this are truncated. Default: 64KB */\n maxBodySize?: number;\n}\n\n/**\n * Captures incoming request data and sends REQUEST/RESPONSE events through\n * the Limelight message protocol. Shared logic used by both Express middleware\n * and Next.js wrapper.\n *\n * @param req Incoming HTTP request object (Node.js IncomingMessage)\n * @param res HTTP response object (Node.js ServerResponse)\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param config Current Limelight configuration object\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns void\n */\nexport const captureRequest = (\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n config: LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n const requestId = generateRequestId();\n const startTime = Date.now();\n const maxBodySize = options?.maxBodySize ?? DEFAULT_MAX_BODY_SIZE;\n\n const traceHeaderName = config?.traceHeaderName ?? \"x-limelight-trace-id\";\n const incomingTraceId = req.headers[traceHeaderName] as string | undefined;\n const traceId = incomingTraceId || generateRequestId();\n (req as any).limelightTraceId = traceId;\n\n const url = req.url || \"/\";\n const method = (req.method || \"GET\").toUpperCase() as HttpMethod;\n\n const headers: Record<string, string> = {};\n\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n headers[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : value;\n }\n }\n\n let requestBody = serializeBody(req.body, config?.disableBodyCapture);\n\n if (requestBody?.raw && requestBody.raw.length > maxBodySize) {\n requestBody = {\n ...requestBody,\n raw: requestBody.raw.slice(0, maxBodySize) + \"...[truncated]\",\n size: requestBody.size,\n };\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.INCOMING,\n url,\n method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: url.split(\"?\")[0]?.split(\"/\").filter(Boolean).pop() ?? \"/\",\n initiator: \"incoming\",\n requestSize: requestBody?.size ?? 0,\n };\n\n if (config?.beforeSend) {\n const modified = config.beforeSend(requestEvent);\n\n if (!modified) return;\n if (modified.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n requestEvent = modified;\n }\n\n sendMessage(requestEvent);\n\n const chunks: Buffer[] = [];\n let totalSize = 0;\n const originalWrite = res.write;\n const originalEnd = res.end;\n\n res.write = (chunk: any, ...args: any[]): boolean => {\n if (chunk && typeof chunk !== \"function\" && totalSize < maxBodySize) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buf);\n totalSize += buf.length;\n }\n\n return originalWrite.apply(res, [chunk, ...args] as any);\n };\n\n res.end = (chunk: any, ...args: any[]): ServerResponse => {\n if (chunk && typeof chunk !== \"function\" && totalSize < maxBodySize) {\n const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n chunks.push(buf);\n totalSize += buf.length;\n }\n\n return originalEnd.apply(res, [chunk, ...args] as any);\n };\n\n res.on(\"finish\", () => {\n const endTime = Date.now();\n const duration = endTime - startTime;\n\n const responseHeaders: Record<string, string> = {};\n const rawHeaders = res.getHeaders();\n\n for (const [key, value] of Object.entries(rawHeaders)) {\n if (value) {\n responseHeaders[key.toLowerCase()] = Array.isArray(value)\n ? value.join(\", \")\n : String(value);\n }\n }\n\n let responseBodyStr: string | undefined;\n\n if (chunks.length > 0 && !config?.disableBodyCapture) {\n const full = Buffer.concat(chunks);\n const fullStr = full.toString(\"utf-8\");\n\n responseBodyStr =\n fullStr.length > maxBodySize\n ? fullStr.slice(0, maxBodySize) + \"...[truncated]\"\n : fullStr;\n }\n\n const responseBody = serializeBody(\n responseBodyStr,\n config?.disableBodyCapture,\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n traceId,\n sessionId: getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.INCOMING,\n status: res.statusCode,\n statusText: res.statusMessage || \"\",\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: res.statusCode >= 200 && res.statusCode < 300,\n };\n\n if (config?.beforeSend) {\n const modified = config.beforeSend(responseEvent);\n if (!modified) return;\n\n if (modified.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return;\n }\n\n responseEvent = modified;\n }\n\n sendMessage(responseEvent);\n });\n};\n\n/**\n * Creates an Express/Connect-compatible middleware that captures incoming\n * HTTP requests and responses, sending them through the Limelight protocol.\n *\n * Place this middleware AFTER body-parser middleware (express.json(), etc.)\n * so that req.body is available for request body capture.\n *\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param getConfig Function to retrieve the current Limelight configuration\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns An Express/Connect middleware function\n */\nexport const createHttpMiddleware = (\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n getConfig: () => LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n return (\n req: IncomingMessage & { body?: unknown },\n res: ServerResponse,\n next: () => void,\n ) => {\n captureRequest(req, res, sendMessage, getSessionId, getConfig(), options);\n\n const traceId = (req as any).limelightTraceId as string | undefined;\n const ctx = getTraceContext();\n\n if (ctx && traceId) {\n ctx.run({ traceId }, next);\n } else {\n next();\n }\n };\n};\n","import type { IncomingMessage, ServerResponse } from \"http\";\nimport { LimelightConfig, LimelightMessage } from \"@/types\";\nimport { captureRequest, MiddlewareOptions } from \"./httpMiddleware\";\nimport { getTraceContext } from \"@/limelight/context\";\n\ntype NextApiHandler = (\n req: IncomingMessage & { body?: unknown; query?: Record<string, unknown> },\n res: ServerResponse,\n) => void | Promise<void>;\n\n/**\n * Wraps a Next.js Pages API route handler with Limelight request/response capture.\n *\n * NOTE: This works with Next.js Pages Router API routes (`pages/api/`)\n * which use the Node.js `(req, res)` signature. It does NOT work with\n * App Router route handlers (`app/api/`) which use the Web Standard\n * `Request`/`Response` objects. App Router support is planned for a future release.\n *\n * @example\n * ```ts\n * // pages/api/users.ts\n * import { Limelight } from '@getlimelight/sdk';\n *\n * export default Limelight.withLimelight((req, res) => {\n * res.json({ ok: true });\n * });\n * ```\n *\n * @param sendMessage Function to send Limelight messages to the server\n * @param getSessionId Function to retrieve the current Limelight session ID\n * @param getConfig Function to retrieve the current Limelight configuration\n * @param options Optional middleware options (e.g. maxBodySize)\n * @returns A function that wraps a Next.js API route handler with Limelight capture\n */\nexport const createWithLimelight = (\n sendMessage: (message: LimelightMessage) => void,\n getSessionId: () => string,\n getConfig: () => LimelightConfig | null,\n options?: MiddlewareOptions,\n) => {\n return (handler: NextApiHandler): NextApiHandler => {\n return (req, res) => {\n captureRequest(req, res, sendMessage, getSessionId, getConfig(), options);\n\n const traceId = (req as any).limelightTraceId as string | undefined;\n const ctx = getTraceContext();\n\n if (ctx && traceId) {\n return ctx.run({ traceId }, () => handler(req, res));\n }\n\n return handler(req, res);\n };\n };\n};\n","import {\n LimelightConfig,\n LimelightMessage,\n RequestBridgeConfig,\n ResponseBridgeConfig,\n} from \"@/types\";\nimport {\n ConsoleInterceptor,\n ErrorInterceptor,\n HttpInterceptor,\n NetworkInterceptor,\n RenderInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { hasDOM, isDevelopment, isServer, safeStringify } from \"@/helpers\";\nimport {\n LIMELIGHT_DESKTOP_WSS_URL,\n LIMELIGHT_MCP_WS_URL,\n LIMELIGHT_WEB_WSS_URL,\n SDK_VERSION,\n WS_PATH,\n} from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\nimport { StateInterceptor } from \"./interceptors/StateInterceptor\";\nimport { RequestBridge } from \"./bridges/RequestBridge\";\nimport { CommandHandler } from \"./handlers/CommandHandler\";\nimport { Command } from \"@/types/commands\";\nimport {\n createHttpMiddleware,\n createWithLimelight,\n MiddlewareOptions,\n} from \"./middleware\";\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 httpInterceptor: HttpInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n private renderInterceptor: RenderInterceptor;\n private stateInterceptor: StateInterceptor;\n private errorInterceptor: ErrorInterceptor;\n private requestBridge: RequestBridge;\n private commandHandler: CommandHandler | null = null;\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.httpInterceptor = new HttpInterceptor(\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 this.stateInterceptor = new StateInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.errorInterceptor = new ErrorInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.requestBridge = new RequestBridge(\n this.sendMessage.bind(this),\n () => this.sessionId,\n );\n this.commandHandler = new CommandHandler(\n { render: this.renderInterceptor },\n this.sendMessage.bind(this),\n () => this.config,\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 const configServerUrl = config?.serverUrl\n ? config.serverUrl\n : config?.target === \"mcp\"\n ? LIMELIGHT_MCP_WS_URL\n : config?.projectKey\n ? `${LIMELIGHT_WEB_WSS_URL}${WS_PATH}`\n : `${LIMELIGHT_DESKTOP_WSS_URL}${WS_PATH}`;\n\n this.config = {\n ...config,\n appName: config?.appName ?? \"Limelight App\",\n serverUrl: configServerUrl,\n enabled: isEnabled,\n enableNetworkInspector: config?.enableNetworkInspector ?? true,\n enableConsole: config?.enableConsole ?? true,\n enableGraphQL: config?.enableGraphQL ?? true,\n enableRenderInspector: config?.enableRenderInspector ?? true,\n enableStateInspector: config?.enableStateInspector ?? true,\n enableInternalLogging: config?.enableInternalLogging ?? false,\n };\n\n if (!this.config?.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n this.requestBridge.setConfig(this.config);\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n\n if (typeof XMLHttpRequest !== \"undefined\") {\n this.xhrInterceptor.setup(this.config);\n }\n\n if (isServer()) {\n this.httpInterceptor.setup(this.config);\n }\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n\n if (isServer()) {\n this.errorInterceptor.setup(this.config);\n }\n }\n\n if (this.config.enableRenderInspector && !isServer()) {\n this.renderInterceptor.setup(this.config);\n }\n\n if (this.config.stores && this.config.enableStateInspector) {\n this.stateInterceptor.setup(this.config);\n }\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\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 this.configure(config);\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === 1 /* WebSocket.OPEN */) {\n if (this.config?.enableInternalLogging) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n }\n\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 this.ws = null;\n }\n\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n }\n return;\n }\n\n const WsConstructor =\n this.config.webSocketImpl ??\n (typeof WebSocket !== \"undefined\" ? WebSocket : undefined);\n\n if (!WsConstructor) {\n if (this.config?.enableInternalLogging) {\n console.error(\n \"[Limelight] WebSocket is not available. Pass webSocketImpl in config (e.g. ws package).\",\n );\n }\n return;\n }\n\n try {\n this.ws = new WsConstructor(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 (hasDOM()\n ? \"web\"\n : typeof process !== \"undefined\"\n ? \"node\"\n : \"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.onmessage = (event) => {\n try {\n const command = JSON.parse(event.data) as Command;\n this.commandHandler?.handle(command);\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to parse command:\", error);\n }\n }\n };\n\n this.ws.onerror = (error) => {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] WebSocket error:\", error);\n }\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to connect:\", error);\n }\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\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 this.connect(this.config || undefined);\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 !== 1 /* WebSocket.OPEN */) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n // Patch sessionId for messages queued before connect()\n if (message && \"sessionId\" in message && !message.sessionId) {\n (message as any).sessionId = this.sessionId;\n }\n this.ws.send(safeStringify(message));\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\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 === 1 /* WebSocket.OPEN */) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === 1 /* WebSocket.OPEN */) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n if (this.config?.enableInternalLogging) {\n console.error(\"[Limelight] Failed to send message:\", error);\n }\n\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n if (this.config?.enableInternalLogging) {\n console.warn(\n \"[Limelight] Message queue full, dropping oldest message\",\n );\n }\n\n this.messageQueue.shift();\n }\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 if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.httpInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n this.errorInterceptor.cleanup();\n this.renderInterceptor.cleanup();\n this.stateInterceptor.cleanup();\n this.requestBridge.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 /**\n * Manually register a request with Limelight.\n * Use this when your app makes network requests outside of fetch/XHR\n * (e.g., through native modules).\n *\n * @param config - Request configuration\n * @returns A request ID to use with endRequest() or failRequest()\n */\n startRequest(config: RequestBridgeConfig): string {\n return this.requestBridge.startRequest(config);\n }\n\n /**\n * Complete a manually tracked request with a successful response.\n *\n * @param requestId - The ID returned from startRequest()\n * @param response - Response data\n */\n endRequest(requestId: string, response: ResponseBridgeConfig): void {\n this.requestBridge.endRequest(requestId, response);\n }\n\n /**\n * Complete a manually tracked request with an error.\n *\n * @param requestId - The ID returned from startRequest()\n * @param error - The error that occurred\n */\n failRequest(requestId: string, error: unknown): void {\n this.requestBridge.failRequest(requestId, error);\n }\n\n /**\n * Returns an Express/Connect-compatible middleware that captures incoming\n * HTTP requests and responses.\n *\n * Place after body-parser middleware (express.json(), etc.) for request body capture.\n *\n * @example\n * ```ts\n * app.use(express.json());\n * app.use(Limelight.middleware());\n * ```\n */\n middleware(options?: MiddlewareOptions) {\n return createHttpMiddleware(\n this.sendMessage.bind(this),\n () => this.sessionId,\n () => this.config,\n options,\n );\n }\n\n /**\n * Wraps a Next.js Pages API route handler with request/response capture.\n * Works with Pages Router (`pages/api/`), not App Router (`app/api/`).\n *\n * @example\n * ```ts\n * // pages/api/users.ts\n * export default Limelight.withLimelight((req, res) => {\n * res.json({ ok: true });\n * });\n * ```\n */\n withLimelight(\n handler: Parameters<ReturnType<typeof createWithLimelight>>[0],\n ) {\n const wrapper = createWithLimelight(\n this.sendMessage.bind(this),\n () => this.sessionId,\n () => this.config,\n );\n return wrapper(handler);\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\nexport type { RequestBridgeConfig, LimelightConfig, LimelightMessage };\n"],"mappings":";;;;;;AAKO,IAAK,eAAL,kBAAKA,kBAAL;AACL,EAAAA,cAAA,SAAM;AACN,EAAAA,cAAA,UAAO;AACP,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,UAAO;AACP,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,WAAQ;AANE,SAAAA;AAAA,GAAA;AAYL,IAAK,gBAAL,kBAAKC,mBAAL;AACL,EAAAA,eAAA,SAAM;AACN,EAAAA,eAAA,aAAU;AACV,EAAAA,eAAA,kBAAe;AACf,EAAAA,eAAA,YAAS;AAJC,SAAAA;AAAA,GAAA;AAUL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,eAAY;AACZ,EAAAA,aAAA,aAAU;AACV,EAAAA,aAAA,aAAU;AACV,EAAAA,aAAA,iBAAc;AACd,EAAAA,aAAA,aAAU;AALA,SAAAA;AAAA,GAAA;;;AChBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,WAAQ;AACR,EAAAA,aAAA,SAAM;AACN,EAAAA,aAAA,aAAU;AACV,EAAAA,aAAA,cAAW;AACX,EAAAA,aAAA,UAAO;AALG,SAAAA;AAAA,GAAA;AAQL,IAAK,eAAL,kBAAKC,kBAAL;AACL,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,cAAW;AACX,EAAAA,cAAA,WAAQ;AACR,EAAAA,cAAA,WAAQ;AALE,SAAAA;AAAA,GAAA;AAQL,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,kBAAe;AACf,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,oBAAiB;AAPP,SAAAA;AAAA,GAAA;AAUL,IAAK,aAAL,kBAAKC,gBAAL;AACL,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,SAAM;AACN,EAAAA,YAAA,WAAQ;AACR,EAAAA,YAAA,YAAS;AACT,EAAAA,YAAA,UAAO;AACP,EAAAA,YAAA,aAAU;AACV,EAAAA,YAAA,WAAQ;AACR,EAAAA,YAAA,aAAU;AATA,SAAAA;AAAA,GAAA;AAYL,IAAK,kBAAL,kBAAKC,qBAAL;AACL,EAAAA,kCAAA,mBAAgB,OAAhB;AACA,EAAAA,kCAAA,aAAU,OAAV;AACA,EAAAA,kCAAA,iBAAc,OAAd;AACA,EAAAA,kCAAA,kBAAe,OAAf;AACA,EAAAA,kCAAA,kBAAe,OAAf;AALU,SAAAA;AAAA,GAAA;AAkGL,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,aAAU;AACV,EAAAA,WAAA,aAAU;AAFA,SAAAA;AAAA,GAAA;;;AC9HL,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,WAAQ;AACR,EAAAA,kBAAA,cAAW;AACX,EAAAA,kBAAA,SAAM;AAHI,SAAAA;AAAA,GAAA;;;ACrBL,IAAK,cAAL,kBAAKC,iBAAL;AACL,EAAAA,aAAA,mBAAgB;AAChB,EAAAA,aAAA,SAAM;AAFI,SAAAA;AAAA,GAAA;;;ACQL,IAAM,oBAAoB,CAC/B,OACA,SACgB;AAChB,QAAM,aAAa,KAChB,IAAI,CAAC,QAAQ;AACZ,QAAI;AACF,aAAO,OAAO,QAAQ,WAAW,KAAK,UAAU,GAAG,IAAI,OAAO,GAAG;AAAA,IACnE,QAAQ;AACN,aAAO,OAAO,GAAG;AAAA,IACnB;AAAA,EACF,CAAC,EACA,KAAK,GAAG,EACR,YAAY;AAEf,MAAI,UAAU,SAAS;AACrB,QACE,WAAW,SAAS,QAAQ,KAC5B,WAAW,SAAS,WAAW,KAC/B,WAAW,SAAS,UAAU,KAC9B,WAAW,SAAS,WAAW,KAC/B,KAAK,KAAK,CAAC,QAAQ,eAAe,KAAK,GACvC;AACA;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,QAAQ;AACpB;AAAA,EACF;AAEA,MACE,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,OAAO,KAC3B,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,UAAU,KAC9B,WAAW,SAAS,MAAM,KAC1B,WAAW,SAAS,KAAK,KACzB,WAAW,SAAS,SAAS,KAC7B,WAAW,SAAS,KAAK,GACzB;AACA;AAAA,EACF;AAEA,MACE,WAAW,SAAS,aAAa,KACjC,WAAW,SAAS,MAAM,KAC1B,WAAW,SAAS,QAAQ,KAC5B,WAAW,SAAS,KAAK,KACzB,WAAW,SAAS,QAAQ,KAC5B,WAAW,SAAS,cAAc,KAClC,WAAW,SAAS,YAAY,GAChC;AACA;AAAA,EACF;AAEA;AACF;;;AC5DO,IAAM,kBAAkB,MAAqB;AAClD,MAAI;AACF,UAAM,QAAQ,IAAI,MAAM,EAAE;AAE1B,QAAI,CAAC,MAAO;AAEZ,UAAM,aAAa,MAAM,MAAM,IAAI;AAEnC,aAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC1C,YAAM,OAAO,WAAW,CAAC;AAEzB,UAAI,SAAS,OAAW;AAExB,UACE,KAAK,SAAS,4BAA4B,KAC1C,KAAK,SAAS,yBAAyB,KACvC,KAAK,SAAS,iBAAiB,KAC/B,KAAK,SAAS,eAAe,GAC7B;AACA;AAAA,MACF;AAEA,UAAI,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,eAAe,GAAG;AACpE;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,SAAS,eAAe,GAAG;AACnC;AAAA,MACF;AAEA,UAAI,CAAC,KAAK,SAAS,eAAe,GAAG;AACnC;AAAA,MACF;AAAA,IACF;AAEA;AAAA,EACF,QAAQ;AACN;AAAA,EACF;AACF;;;ACxCO,IAAM,eAAe,MAAc;AACxC,MAAI;AACF,UAAM,QAAQ,IAAI,MAAM,EAAE;AAC1B,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,QAAQ,MAAM,MAAM,IAAI;AAC9B,UAAM,aAAa,MAAM,CAAC,KAAK,MAAM,CAAC;AAEtC,QAAI,CAAC,WAAY,QAAO;AAExB,UAAM,QAAQ,WAAW,MAAM,8BAA8B;AAC7D,QAAI,OAAO;AACT,YAAM,CAAC,EAAE,cAAc,UAAU,IAAI,IAAI;AACzC,YAAM,WAAW,UAAU,MAAM,GAAG,EAAE,IAAI;AAE1C,aAAO,GAAG,YAAY,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC7C;AAEA,WAAO,WAAW,KAAK;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACtBO,IAAM,qBAAqB,MAAyB;AACzD,MAAI,OAAO,eAAe,YAAa,QAAO;AAC9C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI,OAAO,SAAS,YAAa,QAAO;AACxC,QAAM,IAAI,MAAM,gCAAgC;AAClD;;;ACHO,IAAM,6BAA6B,CACxC,UAC4B;AAC5B,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,MAAM,KAAK,EAAE,WAAW,UAAU,EAAG;AACzC,MAAI,MAAM,KAAK,EAAE,WAAW,cAAc,EAAG;AAE7C;AACF;;;ACZO,IAAM,mBAAmB,CAAC,KAAa,SAAuB;AACnE,QAAM,eAAe,IAAI,YAAY,EAAE,SAAS,SAAS;AAEzD,QAAM,UAAU,OAAO,SAAS,YAAY,SAAS,OAAO,KAAK,MAAM;AAEvE,MAAI,OAAO,YAAY,SAAU,QAAO;AAExC,MAAI;AACF,QAAI,QAAQ,SAAS,SAAS,KAAK,QAAQ,SAAS,iBAAiB,GAAG;AACtE,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAAC;AAET,SAAO;AACT;;;ACLO,IAAM,eAAe,CAAC,SAAgD;AAC3E,MAAI;AAEF,UAAM,SAAS,OAAO,SAAS,WAAW,KAAK,MAAM,IAAI,IAAI;AAG7D,QAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,aAAO;AAAA,IACT;AAGA,QAAI,CAAC,OAAO,SAAS,CAAC,OAAO,eAAe;AAC1C,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,MACL,eAAe,OAAO,iBAAiB;AAAA,MACvC,eAAe,2BAA2B,OAAO,KAAK;AAAA,MACtD,WAAW,OAAO,aAAa;AAAA,MAC/B,OAAO,OAAO,SAAS;AAAA,IACzB;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC7BO,IAAM,yBAAyB,CACpC,SAC4B;AAC5B,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,SAAS,QAAS;AACtB,MAAI,SAAS,WAAY;AACzB,MAAI,SAAS,eAAgB;AAE7B,SAAO;AACT;;;ACbO,IAAM,oBAAoB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,wBAAwB;AAK9B,IAAM,4BAA4B;AAKlC,IAAM,uBAAuB;AAU7B,IAAM,UAAU;AAMhB,IAAM,cACX,OAAyC,WAAkB;AAKtD,IAAM,oBAAoB;AAAA,EAC/B,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,mBAAmB;AAAA,EACnB,wBAAwB;AAAA;AAAA,EACxB,+BAA+B;AAAA;AAAA,EAC/B,qBAAqB;AAAA;AACvB;AAKO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,gBAAgB,OAAO;;;AC/E7B,IAAM,yBAAyB,CACpC,YAC2B;AAC3B,QAAM,WAAW,EAAE,GAAG,QAAQ;AAE9B,SAAO,KAAK,QAAQ,EAAE,QAAQ,CAAC,QAAQ;AACrC,QAAI,kBAAkB,SAAS,IAAI,YAAY,CAAC,GAAG;AACjD,eAAS,GAAG,IAAI;AAAA,IAClB;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ACVO,IAAM,gBAAgB,CAC3B,OACA,WAAW,IACX,SAAS,UACE;AACX,QAAM,OAAO,oBAAI,QAAwB;AAEzC,QAAMC,WAAU,CAAC,KAAc,cAAsB,SAAsB;AACzE,QAAI,QAAQ,KAAM,QAAO;AACzB,QAAI,QAAQ,OAAW,QAAO;AAC9B,QAAI,OAAO,QAAQ,SAAU,QAAO,GAAG,GAAG;AAC1C,QAAI,OAAO,QAAQ,SAAU,QAAO,YAAY,IAAI,eAAe,EAAE;AACrE,QAAI,OAAO,QAAQ,YAAY;AAC7B,aAAO,cAAc,IAAI,QAAQ,WAAW;AAAA,IAC9C;AACA,QAAI,OAAO,QAAQ,SAAU,QAAO;AAEpC,QAAI,gBAAgB,UAAU;AAC5B,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,KAAK,IAAI,GAAG;AAE7B,QAAI,aAAa,QAAW;AAC1B,aAAO,oBAAe,QAAQ;AAAA,IAChC;AAEA,SAAK,IAAI,KAAK,QAAQ,MAAM;AAE5B,QAAI,eAAe,OAAO;AACxB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,IAAI;AAAA,QACV,SAAS,IAAI;AAAA,QACb,OAAO,IAAI;AAAA,QACX,GAAG,OAAO;AAAA,UACR,OAAO,QAAQ,GAAG,EAAE;AAAA,YAClB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,WAAW,OAAO,EAAE,SAAS,CAAC;AAAA,UACnD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,MAAM;AACvB,aAAO,EAAE,QAAQ,QAAQ,OAAO,IAAI,YAAY,EAAE;AAAA,IACpD;AAEA,QAAI,eAAe,QAAQ;AACzB,aAAO,EAAE,QAAQ,UAAU,OAAO,IAAI,SAAS,EAAE;AAAA,IACnD;AAEA,QAAI,eAAe,KAAK;AACtB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,IAAI;AAAA,QACV,SAAS,MAAM,KAAK,IAAI,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM;AAAA,UACpDA,SAAQ,GAAG,eAAe,GAAG,GAAG,IAAI,QAAQ,CAAC,OAAO;AAAA,UACpDA,SAAQ,GAAG,eAAe,GAAG,GAAG,IAAI,QAAQ,CAAC,SAAS;AAAA,QACxD,CAAC;AAAA,MACH;AAAA,IACF;AAEA,QAAI,eAAe,KAAK;AACtB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,IAAI;AAAA,QACV,QAAQ,MAAM,KAAK,GAAG,EAAE;AAAA,UAAI,CAAC,GAAG,MAC9BA,SAAQ,GAAG,eAAe,GAAG,GAAG,IAAI,QAAQ,CAAC,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,SAAS;AAC1B,aAAO,EAAE,QAAQ,WAAW,MAAM,4BAA4B;AAAA,IAChE;AACA,QAAI,eAAe,SAAS;AAC1B,aAAO,EAAE,QAAQ,WAAW,MAAM,4BAA4B;AAAA,IAChE;AAEA,QAAI,eAAe,SAAS;AAC1B,aAAO,EAAE,QAAQ,WAAW,MAAM,iCAAiC;AAAA,IACrE;AAEA,QAAI,eAAe,aAAa;AAC9B,aAAO,EAAE,QAAQ,eAAe,YAAY,IAAI,WAAW;AAAA,IAC7D;AAEA,QAAI,YAAY,OAAO,GAAG,GAAG;AAC3B,YAAM,aAAa;AACnB,aAAO;AAAA,QACL,QAAQ,IAAI,YAAY;AAAA,QACxB,QAAQ,WAAW,UAAU,WAAW;AAAA,QACxC,SACE,WAAW,UAAU,KACjB,MAAM,KAAK,WAAW,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC,IAC1C,IAAI,WAAW,MAAM;AAAA,MAC7B;AAAA,IACF;AAEA,QAAI,OAAO,QAAQ,eAAe,eAAe,KAAK;AACpD,aAAO,EAAE,QAAQ,OAAO,MAAM,IAAI,KAAK;AAAA,IACzC;AAEA,QACE,OAAO,oBAAoB,eAC3B,eAAe,iBACf;AACA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,SAAS,OAAO,YAAY,IAAI,QAAQ,CAAC;AAAA,MAC3C;AAAA,IACF;AAEA,QACE,OACA,OAAQ,IAAY,aAAa,YACjC,OAAQ,IAAY,QAAQ,EAAE,SAAS,eAAe,GACtD;AACA,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MACE,OAAQ,IAAY,SAAS,aACxB,IAAY,KAAK,QAAQ,cACzB,IAAY,QAAQ;AAAA,QAC3B,KAAM,IAAY;AAAA,MACpB;AAAA,IACF;AAEA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI;AAAA,QAAI,CAAC,MAAM,MACpBA,SAAQ,MAAM,eAAe,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG;AAAA,MACjD;AAAA,IACF;AAEA,UAAM,SAA8B,CAAC;AACrC,UAAM,QAAQ,OAAO,eAAe,GAAG;AAEvC,QAAI,SAAS,MAAM,eAAe,MAAM,YAAY,SAAS,UAAU;AACrE,aAAO,SAAS,MAAM,YAAY;AAAA,IACpC;AAEA,eAAW,OAAO,KAAK;AACrB,UAAI,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG,GAAG;AAClD,YAAI;AACF,iBAAO,GAAG,IAAIA;AAAA,YACX,IAAY,GAAG;AAAA,YAChB,eAAe;AAAA,YACf,GAAG,IAAI,IAAI,GAAG;AAAA,UAChB;AAAA,QACF,SAAS,GAAG;AACV,iBAAO,GAAG,IACR,8BAA8B,aAAa,QAAQ,EAAE,UAAU,OAAO,CAAC,CAAC;AAAA,QAC5E;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,YAAYA,SAAQ,OAAO,GAAG,MAAM;AAC1C,WAAO,KAAK,UAAU,WAAW,MAAM,SAAS,IAAI,MAAS;AAAA,EAC/D,SAAS,OAAO;AACd,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS;AAAA,MACT,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAChE,CAAC;AAAA,EACH;AACF;;;ACtKO,IAAM,gBAAgB,CAC3B,OACA,uBAC+B;AAC/B,MAAI,oBAAoB;AACtB,WAAO,EAAE,2BAAyB,MAAM,GAAG,SAAS,GAAG;AAAA,EACzD;AAEA,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI;AAEF,QAAI,OAAO,UAAU,UAAU;AAC7B,YAAM,OAAO,KAAK,UAAU,KAAK;AACjC,aAAO;AAAA,QACL;AAAA,QACA,MAAM,KAAK;AAAA,QACX,SAAS,KAAK,MAAM,GAAG,GAAG;AAAA,QAC1B,KAAK;AAAA,MACP;AAAA,IACF;AAGA,QAAI,OAAO,UAAU,UAAU;AAC7B,aAAO;AAAA,QACL;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM,MAAM,GAAG,GAAG;AAAA,QAC3B,KAAK;AAAA,MACP;AAAA,IACF;AAGA,QAAI,OAAO,aAAa,eAAe,iBAAiB,UAAU;AAChE,aAAO;AAAA,QACL;AAAA,QACA,MAAM;AAAA,QACN,SAAS;AAAA,MACX;AAAA,IACF;AAGA,QAAI,OAAO,SAAS,eAAe,iBAAiB,MAAM;AACxD,aAAO;AAAA,QACL;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAGA,QAAI,iBAAiB,aAAa;AAChC,aAAO;AAAA,QACL;AAAA,QACA,MAAM,MAAM;AAAA,QACZ,SAAS;AAAA,MACX;AAAA,IACF;AAGA,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,SAAS,OAAO,KAAK;AAAA,IACvB;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AACF;;;ACpFO,IAAM,gBAAgB,MAAe;AAC1C,MAAI;AACF,UAAM,IAAI;AAIV,QAAI,OAAO,EAAE,YAAY,YAAa,QAAO,CAAC,CAAC,EAAE;AAGjD,QAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,UAAU;AAC3D,aAAO,QAAQ,IAAI,aAAa;AAAA,IAClC;AAOA,UAAM,aAAc,EAAU,QAAQ;AACtC,QAAI,YAAY,KAAK,KAAK;AACxB,aAAO;AAAA,IACT;AAIA,QAAI,OAAO,EAAE,WAAW,eAAe,EAAE,OAAO,MAAM,KAAK,KAAK;AAC9D,aAAO;AAAA,IACT;AAAA,EACF,SAAS,GAAG;AAEV,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;AC/BO,IAAM,oBAAoB,CAAC,QAAgB;AAChD,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,UAAM,OAAO,OAAO;AACpB,UAAM,WAAW,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,WAAO,SAAS,SAAS,SAAS,CAAC,KAAK,QAAQ;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACZO,IAAM,SAAS,MACpB,OAAO,WAAW,eAAe,OAAO,aAAa;AAKhD,IAAM,WAAW,MACtB,CAAC,OAAO,KACR,OAAO,YAAY,eACnB,OAAO,QAAQ,aAAa,eAC5B,OAAO,QAAQ,SAAS,SAAS;;;ACdnC,IAAI,UAAU;AASP,IAAM,mBAAmB,MAAc;AAC5C,QAAM,YAAY,KAAK,IAAI,EAAE,SAAS,EAAE;AACxC,QAAM,SAAS,WAAW,SAAS,EAAE;AACrC,QAAM,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,CAAC;AAGxD,MAAI,UAAU,IAAM,WAAU;AAE9B,SAAO,GAAG,SAAS,GAAG,KAAK,IAAI,MAAM;AACvC;;;ACZO,IAAM,4BAA4B,MAGpC;AACH,SAAO;AAAA,IACL,kCAA6B,GAAG;AAAA,IAChC,kCAA6B,GAAG;AAAA,IAChC,sCAA+B,GAAG;AAAA,IAClC,oCAA8B,GAAG;AAAA,IACjC,kCAA6B,GAAG;AAAA,IAChC,wBAAwB,GAAG;AAAA,EAC7B;AACF;;;ACZO,IAAM,6BAA6B,MAAuB;AAC/D,SAAO;AAAA,IACL,aAAa,oBAAI,IAAI;AAAA,IACrB,oBAAoB,oBAAI,IAAI;AAAA,EAC9B;AACF;;;ACVA,IAAI,yBAAuD;AAOpD,IAAM,0BAA0B,MAAqB;AAC1D,SAAO,yBAAyB,KAAK;AACvC;;;ACDO,IAAM,aAAa,CACxB,UACA,YACW;AACX,QAAM,OAAO,QAAQ,YAAY,QAAQ,QAAQ;AACjD,QAAM,OAAO,QAAQ,OAAO,IAAI,QAAQ,IAAI,KAAK;AACjD,QAAM,OAAO,QAAQ,QAAQ;AAC7B,SAAO,GAAG,QAAQ,KAAK,IAAI,GAAG,IAAI,GAAG,IAAI;AAC3C;;;ACVO,IAAM,sBAAsB,CAAC,gBAAiC;AACnE,SAAO,qBAAqB;AAAA,IAAK,CAAC,SAChC,YAAY,YAAY,EAAE,SAAS,IAAI;AAAA,EACzC;AACF;;;ACFO,IAAM,qBAAN,MAAyB;AAAA,EAO9B,YACU,aACA,cACR;AAFQ;AACA;AAAA,EACP;AAAA,EATK,kBAAoC,CAAC;AAAA,EACrC,UAAU;AAAA,EACV,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,SAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAczC,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,gDAAgD;AAAA,MAC/D;AAEA;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAMC,QAAO;AACb,UAAM,UAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOhC;AAEA,YAAQ,QAAQ,CAAC,UAAU;AACzB,YAAM,WAAW,QAAQ,KAAK;AAC9B,WAAK,gBAAgB,KAAK,IAAI;AAE9B,cAAQ,KAAK,IAAI,YAAa,MAAa;AACzC,YAAIA,MAAK,eAAe;AACtB,iBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,QACrC;AAEA,QAAAA,MAAK,gBAAgB;AAErB,YAAI;AACF,gBAAM,SAAS,gBAAgB;AAC/B,gBAAM,cAAc,kBAAkB,OAAO,IAAI;AACjD,gBAAM,aAAaA,MAAK,kBAAkB;AAE1C,cAAI,eAA6B;AAAA,YAC/B,IAAI,GAAGA,MAAK,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,IAAIA,MAAK,SAAS;AAAA,YAC1D,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA,WAAW,KAAK,IAAI;AAAA,YACpB,WAAWA,MAAK,aAAa;AAAA,YAC7B;AAAA,YACA;AAAA,YACA,MAAM,KAAK,IAAI,CAAC,QAAQ,cAAc,GAAG,CAAC;AAAA,YAC1C;AAAA,UACF;AAEA,cAAIA,MAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgBA,MAAK,OAAO,WAAW,YAAY;AAEzD,gBAAI,CAAC,eAAe;AAClB,qBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,YACrC;AAEA,gBAAI,cAAc,UAAU,WAAW;AAErC,sBAAQ;AAAA,gBACN;AAAA,cACF;AACA,qBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,YACrC;AAEA,2BAAe;AAAA,UACjB;AAEA,UAAAA,MAAK,YAAY,YAAY;AAAA,QAC/B,SAAS,OAAO;AAAA,QAEhB,UAAE;AACA,UAAAA,MAAK,gBAAgB;AAAA,QACvB;AAEA,eAAO,SAAS,MAAM,SAAS,IAAI;AAAA,MACrC;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAwC;AAC9C,QAAI;AACF,YAAM,QAAQ,IAAI,MAAM;AACxB,YAAM,QAAQ,MAAM;AAEpB,UAAI,CAAC,MAAO,QAAO;AAEnB,YAAM,gBAAgB,MACnB,MAAM,IAAI,EACV,MAAM,CAAC,EACP;AAAA,QACC,CAAC,SACC,CAAC,KAAK,SAAS,oBAAoB,KAAK,CAAC,KAAK,SAAS,WAAW;AAAA,MACtE;AAEF,aAAO,cAAc,SAAS,IAAI,cAAc,KAAK,IAAI,IAAI;AAAA,IAC/D,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,4CAA4C;AAAA,MAC3D;AAEA;AAAA,IACF;AACA,SAAK,UAAU;AAEf,WAAO,QAAQ,KAAK,eAAe,EAAE,QAAQ,CAAC,CAAC,QAAQ,EAAE,MAAM;AAC7D,UAAI,IAAI;AACN,QAAC,QAAgB,MAAM,IAAI;AAAA,MAC7B;AAAA,IACF,CAAC;AAED,SAAK,kBAAkB,CAAC;AAAA,EAC1B;AACF;;;ACxJO,IAAM,kBAAkB,MAAc;AAC3C,SAAO,GAAG,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AACjE;AAOO,IAAM,oBAAoB,MAAc;AAC7C,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,CAAC,CAAC;AACrE;;;ACPA,IAAI,YAAY;AAChB,IAAI;AAQG,IAAM,kBAAkB,MAAoC;AACjE,MAAI,CAAC,WAAW;AACd,gBAAY;AACZ,QAAI;AAGF,YAAM,WAAW,WAAW,SAAS;AACrC,YAAM,EAAE,kBAAkB,IAAI,SAAS,kBAAkB;AAEzD,sBAAgB,IAAI,kBAAkB;AAAA,IACxC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;;;ACbO,IAAM,qBAAN,MAAyB;AAAA,EAO9B,YACU,aACA,cACR;AAFQ;AACA;AAER,SAAK,eAAe,mBAAmB;AACvC,QAAI,OAAO,KAAK,aAAa,UAAU,YAAY;AACjD,WAAK,gBAAgB,KAAK,aAAa,MAAM,KAAK,KAAK,YAAY;AAAA,IACrE;AAAA,EACF;AAAA,EAdQ;AAAA,EAEA,SAAiC;AAAA,EACjC,UAAU;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBR,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,gDAAgD;AAAA,MAC/D;AAEA;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,eAAe;AACvB,UAAI,QAAQ,uBAAuB;AACjC,gBAAQ;AAAA,UACN;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAMC,QAAO;AACb,UAAM,gBAAgB,KAAK;AAE3B,SAAK,aAAa,QAAQ,eACxB,OACA,OAAoB,CAAC,GACF;AACnB,YAAM,YAAY,kBAAkB;AACpC,YAAM,YAAY,KAAK,IAAI;AAE3B,YAAM,MACJ,OAAO,UAAU,WACb,QACA,iBAAiB,MACf,MAAM,SAAS,IACf,MAAM;AAEd,YAAM,SAAU,KAAK,UAAU;AAE/B,YAAM,eAAe,EAAE,GAAG,KAAK;AAE/B,YAAM,UAAkC,CAAC;AAEzC,UAAI,aAAa,mBAAmB,SAAS;AAC3C,qBAAa,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC3C,kBAAQ,IAAI,YAAY,CAAC,IAAI;AAAA,QAC/B,CAAC;AAAA,MACH,WAAW,aAAa,SAAS;AAC/B,eAAO,QAAQ,aAAa,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AAC7D,kBAAQ,IAAI,YAAY,CAAC,IAAI;AAAA,QAC/B,CAAC;AAAA,MACH;AAEA,cAAQ,yBAAyB,IAAI;AAErC,YAAM,kBACJA,MAAK,QAAQ,mBAAmB;AAElC,UAAI,CAAC,QAAQ,eAAe,GAAG;AAC7B,cAAM,kBAAkB,gBAAgB,GAAG,SAAS,GAAG;AACvD,gBAAQ,eAAe,IAAI,mBAAmB,kBAAkB;AAAA,MAClE;AAEA,YAAM,UAAU,QAAQ,eAAe;AAEvC,mBAAa,UAAU,IAAI,QAAQ,OAAO;AAE1C,UAAI,yBAAyB,KAAK;AAElC,UAAI,iBAAiB,WAAW,CAAC,wBAAwB;AACvD,YAAI;AACF,gBAAM,gBAAgB,MAAM,MAAM;AAClC,gBAAM,cAAc,cAAc,QAAQ,IAAI,cAAc,KAAK;AAEjE,cACE,YAAY,SAAS,kBAAkB,KACvC,YAAY,SAAS,OAAO,GAC5B;AACA,qCAAyB,MAAM,cAAc,KAAK;AAAA,UACpD,OAAO;AACL,qCAAyB,MAAM,cAAc,KAAK;AAAA,UACpD;AAAA,QACF,QAAQ;AACN,mCAAyB;AAEzB,cAAIA,MAAK,QAAQ,uBAAuB;AACtC,oBAAQ;AAAA,cACN;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,cAAc;AAAA,QAClB;AAAA,QACAA,MAAK,QAAQ;AAAA,MACf;AAEA,UAAI,cAAyC;AAE7C,UAAIA,MAAK,QAAQ,iBAAiB,iBAAiB,KAAK,WAAW,GAAG;AACpE,cAAM,UAAU,aAAa;AAE7B,YAAI,SAAS;AACX,wBAAc,aAAa,OAAO,KAAK;AAAA,QACzC;AAAA,MACF;AAEA,UAAI,eAAiC;AAAA,QACnC,IAAI;AAAA,QACJ;AAAA,QACA,WAAWA,MAAK,aAAa;AAAA,QAC7B,WAAW;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,uBAAuB,OAAO;AAAA,QACvC,MAAM;AAAA,QACN,MAAM,kBAAkB,GAAG;AAAA,QAC3B,WAAW,aAAa;AAAA,QACxB,aAAa,aAAa,QAAQ;AAAA,QAClC,SAAS;AAAA,MACX;AAEA,UAAIA,MAAK,QAAQ,YAAY;AAC3B,cAAM,gBAAgBA,MAAK,OAAO,WAAW,YAAY;AAEzD,YAAI,CAAC,eAAe;AAClB,iBAAO,cAAc,OAAO,YAAY;AAAA,QAC1C;AAEA,YAAI,cAAc,mCAAgC;AAEhD,kBAAQ,MAAM,oDAAoD;AAClE,iBAAO,cAAc,OAAO,YAAY;AAAA,QAC1C;AAEA,uBAAe;AAAA,MACjB;AAEA,MAAAA,MAAK,YAAY,YAAY;AAE7B,UAAI;AACF,cAAM,WAAW,MAAM,cAAc,OAAO,YAAY;AACxD,cAAM,QAAQ,SAAS,MAAM;AAC7B,cAAM,UAAU,KAAK,IAAI;AACzB,cAAM,WAAW,UAAU;AAC3B,cAAM,kBAA0C,CAAC;AAEjD,iBAAS,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AACvC,0BAAgB,GAAG,IAAI;AAAA,QACzB,CAAC;AAED,YAAI;AAEJ,YAAI;AACF,yBAAe,MAAM,MAAM,KAAK;AAAA,QAClC,SAAS,YAAY;AACnB,yBAAe;AAAA,QACjB;AAEA,cAAM,eAAe;AAAA,UACnB;AAAA,UACAA,MAAK,QAAQ;AAAA,QACf;AAEA,YAAI,gBAAkC;AAAA,UACpC,IAAI;AAAA,UACJ;AAAA,UACA,WAAWA,MAAK,aAAa;AAAA,UAC7B,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,QAAQ,SAAS;AAAA,UACjB,YAAY,SAAS;AAAA,UACrB,SAAS,uBAAuB,eAAe;AAAA,UAC/C,MAAM;AAAA,UACN;AAAA,UACA,cAAc,cAAc,QAAQ;AAAA,UACpC,YAAY,SAAS;AAAA,UACrB,IAAI,SAAS;AAAA,QACf;AAEA,YAAIA,MAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgBA,MAAK,OAAO,WAAW,aAAa;AAE1D,cAAI,CAAC,eAAe;AAClB,mBAAO;AAAA,UACT;AAEA,cAAI,cAAc,qCAAiC;AAEjD,oBAAQ,MAAM,oDAAoD;AAClE,mBAAO;AAAA,UACT;AAEA,0BAAgB;AAAA,QAClB;AAEA,QAAAA,MAAK,YAAY,aAAa;AAC9B,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,UACJ,eAAe,UACd,IAAI,SAAS,gBAAgB,IAAI,QAAQ,SAAS,SAAS;AAE9D,cAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpE,cAAM,aAAa,eAAe,QAAQ,IAAI,QAAQ;AAEtD,YAAI,aAAgC;AAAA,UAClC,IAAI;AAAA,UACJ;AAAA,UACA,WAAWA,MAAK,aAAa;AAAA,UAC7B,WAAW,KAAK,IAAI;AAAA,UACpB,OAAO;AAAA,UACP;AAAA,UACA,cAAc,UAAU,oBAAoB;AAAA,UAC5C,OAAO;AAAA,QACT;AAEA,YAAIA,MAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgBA,MAAK,OAAO,WAAW,UAAU;AAEvD,cACE,kBACC,cAAc,iCACb,cAAc,gCAChB;AACA,yBAAa;AAAA,UACf;AAAA,QACF;AAEA,QAAAA,MAAK,YAAY,UAAU;AAC3B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,4CAA4C;AAAA,MAC3D;AAEA;AAAA,IACF;AAEA,SAAK,UAAU;AACf,QAAI,KAAK,eAAe;AACtB,WAAK,aAAa,QAAQ,KAAK;AAAA,IACjC;AAAA,EACF;AACF;;;AC9QO,IAAM,iBAAN,MAAqB;AAAA,EAQ1B,YACU,aACA,cACR;AAFQ;AACA;AAER,QAAI,OAAO,mBAAmB,aAAa;AACzC,WAAK,kBAAkB,eAAe,UAAU;AAChD,WAAK,kBAAkB,eAAe,UAAU;AAChD,WAAK,8BACH,eAAe,UAAU;AAAA,IAC7B;AAAA,EACF;AAAA,EAjBQ;AAAA,EACA;AAAA,EACA;AAAA,EAEA,UAAU;AAAA,EACV,SAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBzC,MAAM,QAAyB;AAC7B,QAAI,OAAO,mBAAmB,aAAa;AACzC;AAAA,IACF;AAEA,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,4CAA4C;AAAA,MAC3D;AAEA;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAMC,QAAO;AAEb,mBAAe,UAAU,OAAO,SAAU,QAAgB,KAAa;AACrE,WAAK,iBAAiB;AAAA,QACpB,IAAI,kBAAkB;AAAA,QACtB;AAAA,QACA;AAAA,QACA,SAAS,CAAC;AAAA,QACV,WAAW,KAAK,IAAI;AAAA,QACpB,WAAW,oBAAI,IAAI;AAAA,MACrB;AAEA,aAAOA,MAAK,gBAAgB;AAAA,QAC1B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,mBAAe,UAAU,mBAAmB,SAC1C,QACA,OACA;AACA,UAAI,KAAK,gBAAgB;AACvB,aAAK,eAAe,QAAQ,MAAM,IAAI;AAEtC,YACE,OAAO,YAAY,MAAM,6BACzB,UAAU,SACV;AACA,eAAK,eAAe,gBAAgB;AAAA,QACtC;AAAA,MACF;AAEA,aAAOA,MAAK,4BAA4B,MAAM,MAAM,SAAgB;AAAA,IACtE;AAEA,mBAAe,UAAU,OAAO,SAAU,MAAM;AAC9C,YAAM,OAAO,KAAK;AAElB,UAAI,MAAM,eAAe;AACvB,eAAOA,MAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,MAC1D;AAEA,UAAI,MAAM;AACR,cAAM,kBACJA,MAAK,QAAQ,mBAAmB;AAElC,YAAI,CAAC,KAAK,QAAQ,eAAe,GAAG;AAClC,eAAK,UAAU,kBAAkB;AACjC,UAAAA,MAAK,4BAA4B;AAAA,YAC/B;AAAA,YACA;AAAA,YACA,KAAK;AAAA,UACP;AAAA,QACF,OAAO;AACL,eAAK,UAAU,KAAK,QAAQ,eAAe;AAAA,QAC7C;AAEA,cAAM,cAAc;AAAA,UAClB;AAAA,UACAA,MAAK,QAAQ;AAAA,QACf;AAEA,YAAI,eAAiC;AAAA,UACnC,IAAI,KAAK;AAAA,UACT,SAAS,KAAK;AAAA,UACd,WAAWA,MAAK,aAAa;AAAA,UAC7B,WAAW,KAAK;AAAA,UAChB;AAAA,UACA;AAAA,UACA,KAAK,KAAK;AAAA,UACV,QAAQ,KAAK;AAAA,UACb,SAAS,uBAAuB,KAAK,OAAO;AAAA,UAC5C,MAAM;AAAA,UACN,MAAM,kBAAkB,KAAK,GAAG;AAAA,UAChC,WAAW,aAAa;AAAA,UACxB,aAAa,aAAa,QAAQ;AAAA,QACpC;AAEA,YAAIA,MAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgBA,MAAK,OAAO,WAAW,YAAY;AAEzD,cAAI,CAAC,eAAe;AAClB,mBAAOA,MAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,UAC1D;AAEA,cAAI,cAAc,mCAAgC;AAEhD,oBAAQ,MAAM,oDAAoD;AAClE,mBAAOA,MAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,UAC1D;AAEA,yBAAe;AAAA,QACjB;AAEA,QAAAA,MAAK,YAAY,YAAY;AAC7B,YAAI,eAAe;AAKnB,cAAM,UAAU,MAAM;AACpB,cAAI,KAAK,WAAW;AAClB,iBAAK,UAAU,QAAQ,CAAC,UAAU,UAAU;AAC1C,mBAAK,oBAAoB,OAAO,QAAQ;AAAA,YAC1C,CAAC;AACD,iBAAK,UAAU,MAAM;AAAA,UACvB;AAEA,iBAAO,KAAK;AAAA,QACd;AAMA,cAAM,eAAe,MAAM;AACzB,cAAI,aAAc;AAElB,yBAAe;AAEf,gBAAM,UAAU,KAAK,IAAI;AACzB,gBAAM,WAAW,UAAU,KAAK;AAChC,gBAAM,kBAAkBA,MAAK;AAAA,YAC3B,KAAK,sBAAsB;AAAA,UAC7B;AAEA,cAAI;AAEJ,gBAAM,eAAe,KAAK,gBAAgB;AAE1C,cAAI,iBAAiB,MAAM,iBAAiB,QAAQ;AAClD,2BAAe,KAAK;AAAA,UACtB,WACE,iBAAiB,UACjB,iBAAiB,eACjB;AACA,2BAAe,iBAAiB,YAAY;AAAA,UAC9C,WAAW,iBAAiB,QAAQ;AAClC,2BAAe,KAAK;AAAA,UACtB,OAAO;AACL,2BAAe,KAAK;AAAA,UACtB;AAEA,gBAAM,eAAe;AAAA,YACnB;AAAA,YACAA,MAAK,QAAQ;AAAA,UACf;AAEA,cAAI,gBAAkC;AAAA,YACpC,IAAI,KAAK;AAAA,YACT,SAAS,KAAK;AAAA,YACd,WAAWA,MAAK,aAAa;AAAA,YAC7B,WAAW;AAAA,YACX;AAAA,YACA;AAAA,YACA,QAAQ,KAAK;AAAA,YACb,YAAY,KAAK;AAAA,YACjB,SAAS,uBAAuB,eAAe;AAAA,YAC/C,MAAM;AAAA,YACN;AAAA,YACA,cAAc,cAAc,QAAQ;AAAA,YACpC,YAAY;AAAA,YACZ,IAAI,KAAK,UAAU,OAAO,KAAK,SAAS;AAAA,UAC1C;AAEA,cAAIA,MAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgBA,MAAK,OAAO,WAAW,aAAa;AAE1D,gBAAI,CAAC,eAAe;AAClB;AAAA,YACF;AAEA,gBAAI,cAAc,qCAAiC;AAEjD,sBAAQ;AAAA,gBACN;AAAA,cACF;AACA;AAAA,YACF;AAEA,4BAAgB;AAAA,UAClB;AAEA,UAAAA,MAAK,YAAY,aAAa;AAC9B,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAMA,cAAM,YAAY,CAChB,cACA,gCACG;AACH,cAAI,aAAc;AAElB,yBAAe;AAEf,cAAI,aAAgC;AAAA,YAClC,IAAI,KAAK;AAAA,YACT,SAAS,KAAK;AAAA,YACd,WAAWA,MAAK,aAAa;AAAA,YAC7B,WAAW,KAAK,IAAI;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,cAAIA,MAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgBA,MAAK,OAAO,WAAW,UAAU;AAEvD,gBAAI,iBAAiB,cAAc,+BAA8B;AAC/D,2BAAa;AAAA,YACf;AAAA,UACF;AAEA,UAAAA,MAAK,YAAY,UAAU;AAC3B,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAEA,cAAM,0BAA0B,WAAgC;AAC9D,eACG,KAAK,eAAe,KAAK,KAAK,eAAe,MAC9C,KAAK,WAAW,GAChB;AACA,yBAAa,KAAK,IAAI;AAAA,UACxB;AAAA,QACF;AAEA,cAAM,cAAc,WAAgC;AAClD,uBAAa,KAAK,IAAI;AAAA,QACxB;AAEA,cAAM,eAAe,WAAgC;AACnD,oBAAU,wBAAwB;AAClC,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAEA,cAAM,eAAe,WAAgC;AACnD,oBAAU,sCAAqC;AAC/C,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAEA,cAAM,iBAAiB,WAAgC;AACrD,oBAAU,iBAAiB;AAC3B,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAEA,cAAM,iBAAiB,WAAgC;AACrD,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAEA,aAAK,iBAAiB,oBAAoB,uBAAuB;AACjE,aAAK,iBAAiB,QAAQ,WAAW;AACzC,aAAK,iBAAiB,SAAS,YAAY;AAC3C,aAAK,iBAAiB,SAAS,YAAY;AAC3C,aAAK,iBAAiB,WAAW,cAAc;AAC/C,aAAK,iBAAiB,WAAW,cAAc;AAE/C,aAAK,UAAW,IAAI,oBAAoB,uBAAuB;AAC/D,aAAK,UAAW,IAAI,QAAQ,WAAW;AACvC,aAAK,UAAW,IAAI,SAAS,YAAY;AACzC,aAAK,UAAW,IAAI,SAAS,YAAY;AACzC,aAAK,UAAW,IAAI,WAAW,cAAc;AAC7C,aAAK,UAAW,IAAI,WAAW,cAAc;AAAA,MAC/C;AAEA,aAAOA,MAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,IAC1D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,qBAAqB,cAA8C;AACzE,UAAM,UAAkC,CAAC;AAEzC,iBAAa,MAAM,MAAM,EAAE,QAAQ,CAAC,SAAS;AAC3C,YAAM,aAAa,KAAK,QAAQ,IAAI;AACpC,UAAI,aAAa,GAAG;AAClB,cAAM,MAAM,KAAK,UAAU,GAAG,UAAU;AACxC,cAAM,QAAQ,KAAK,UAAU,aAAa,CAAC;AAC3C,gBAAQ,GAAG,IAAI;AAAA,MACjB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS;AACjB;AAAA,IACF;AACA,SAAK,UAAU;AAEf,QAAI,OAAO,mBAAmB,aAAa;AACzC,qBAAe,UAAU,OAAO,KAAK;AACrC,qBAAe,UAAU,OAAO,KAAK;AACrC,qBAAe,UAAU,mBACvB,KAAK;AAAA,IACT;AAAA,EACF;AACF;;;AC5WO,IAAM,kBAAN,MAAsB;AAAA,EAY3B,YACU,aACA,cACR;AAFQ;AACA;AAER,QAAI;AACF,YAAM,WAAW,WAAW,SAAS;AACrC,WAAK,aAAa,SAAS,MAAM;AACjC,WAAK,cAAc,SAAS,OAAO;AAEnC,WAAK,sBAAsB,KAAK,WAAY;AAC5C,WAAK,kBAAkB,KAAK,WAAY;AACxC,WAAK,uBAAuB,KAAK,YAAa;AAC9C,WAAK,mBAAmB,KAAK,YAAa;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EA3BQ,sBAAkD;AAAA,EAClD,kBAA0C;AAAA,EAC1C,uBAAoD;AAAA,EACpD,mBAA4C;AAAA,EAE5C,aAAiC;AAAA,EACjC,cAAmC;AAAA,EAEnC,SAAiC;AAAA,EACjC,UAAU;AAAA,EAoBlB,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,6CAA6C;AAAA,MAC5D;AAEA;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,aAAa;AACzC,UAAI,QAAQ,uBAAuB;AACjC,gBAAQ;AAAA,UACN;AAAA,QACF;AAAA,MACF;AAEA;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAMC,QAAO;AACb,UAAM,UAAU,KAAK;AACrB,UAAM,WAAW,KAAK;AAEtB,YAAQ,UAAU,IAAI,SAAgB;AACpC,aAAOA,MAAK;AAAA,QACV;AAAA,QACAA,MAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,MAAM,IAAI,SAAgB;AAChC,YAAM,MAAMA,MAAK;AAAA,QACf;AAAA,QACAA,MAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,UAAI,IAAI;AACR,aAAO;AAAA,IACT;AAEA,aAAS,UAAU,IAAI,SAAgB;AACrC,aAAOA,MAAK;AAAA,QACV;AAAA,QACAA,MAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,aAAS,MAAM,IAAI,SAAgB;AACjC,YAAM,MAAMA,MAAK;AAAA,QACf;AAAA,QACAA,MAAK;AAAA,QACL;AAAA,QACA;AAAA,MACF;AACA,UAAI,IAAI;AACR,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,iBACN,UACA,gBACA,QACA,MACoB;AACpB,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QAAI,OAAO,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,aAAa,KAAK;AACzD,YAAM,KAAK,CAAC;AAEZ,UAAI,OAAO,KAAK,CAAC,MAAM,YAAY;AACjC,kBAAU,CAAC;AACX,mBAAW,KAAK,CAAC;AAAA,MACnB,OAAO;AACL,kBAAU,KAAK,CAAC,KAAK,CAAC;AACtB,mBAAW,KAAK,CAAC;AAAA,MACnB;AAAA,IACF,OAAO;AACL,gBAAU,KAAK,CAAC,KAAK,CAAC;AACtB,iBAAW,KAAK,CAAC;AAAA,IACnB;AAEA,QAAI;AAEJ,QAAI,KAAK;AACP,oBAAc,IAAI,SAAS;AAAA,IAC7B,OAAO;AACL,oBAAc,WAAW,UAAU,OAAO;AAAA,IAC5C;AAEA,UAAM,qBAAqB,KAAK,QAAQ,aAAa;AAErD,QAAI,sBAAsB,YAAY,SAAS,kBAAkB,GAAG;AAClE,aAAO,eAAe,MAAM,QAAQ,IAAW;AAAA,IACjD;AAEA,UAAMA,QAAO;AACb,UAAM,YAAY,kBAAkB;AACpC,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,YAAY,aAAa;AAE/B,UAAM,kBACJ,KAAK,QAAQ,mBAAmB;AAClC,UAAM,kBAAkB,gBAAgB,GAAG,SAAS,GAAG;AACvD,UAAM,UAAU,mBAAmB,kBAAkB;AAErD,QAAI,CAAC,QAAQ,SAAS;AACpB,cAAQ,UAAU,CAAC;AAAA,IACrB;AAEA,IAAC,QAAQ,QAAmC,eAAe,IAAI;AAE/D,UAAM,UAAU,QAAQ,UAAU,OAAO,YAAY;AAErD,QAAI;AAEJ,QAAI,KAAK;AACP,oBAAc,WAAW,CAAC,KAAK,SAAS,QAAQ,IAAI,CAAC,KAAK,OAAO;AAAA,IACnE,OAAO;AACL,oBAAc,WAAW,CAAC,SAAS,QAAQ,IAAI,CAAC,OAAO;AAAA,IACzD;AAEA,UAAM,MAA0B,eAAe;AAAA,MAC7C;AAAA,MACA;AAAA,IACF;AAEA,UAAM,aAAuB,CAAC;AAC9B,QAAI,gBAAgB;AACpB,QAAI,mBAAmB;AACvB,UAAM,gBAAgB,IAAI,MAAM,KAAK,GAAG;AACxC,UAAM,cAAc,IAAI,IAAI,KAAK,GAAG;AAEpC,QAAI,QAAQ,CACV,OACA,oBACAC,cACY;AACZ,UAAI,SAAS,gBAAgB,eAAe;AAC1C,cAAM,MAAM,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AAC9D,mBAAW,KAAK,GAAG;AACnB,yBAAiB,IAAI;AAAA,MACvB;AACA,aAAO,cAAc,OAAO,oBAA2BA,SAAe;AAAA,IACxE;AAEA,QAAI,MAAM,CACR,OACA,oBACAA,cACuB;AACvB,UACE,SACA,OAAO,UAAU,cACjB,gBAAgB,eAChB;AACA,cAAM,MAAM,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AAC9D,mBAAW,KAAK,GAAG;AACnB,yBAAiB,IAAI;AAAA,MACvB;AAEA,UAAI,CAAC,kBAAkB;AACrB,2BAAmB;AAEnB,cAAM,WACJ,WAAW,SAAS,IAChB,OAAO,OAAO,UAAU,EAAE,SAAS,OAAO,IAC1C;AAEN,cAAM,UAAkC,CAAC;AACzC,cAAM,aAAa,IAAI,WAAW;AAElC,mBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,cAAI,UAAU,QAAW;AACvB,oBAAQ,IAAI,YAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,IAC5C,MAAM,KAAK,IAAI,IACf,OAAO,KAAK;AAAA,UAClB;AAAA,QACF;AAEA,cAAM,cAAc;AAAA,UAClB;AAAA,UACAD,MAAK,QAAQ;AAAA,QACf;AAEA,YAAI,eAAiC;AAAA,UACnC,IAAI;AAAA,UACJ;AAAA,UACA,WAAWA,MAAK,aAAa;AAAA,UAC7B,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,KAAK;AAAA,UACL;AAAA,UACA,SAAS,uBAAuB,OAAO;AAAA,UACvC,MAAM;AAAA,UACN,MAAM,kBAAkB,WAAW;AAAA,UACnC;AAAA,UACA,aAAa,aAAa,QAAQ;AAAA,QACpC;AAEA,YAAIA,MAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgBA,MAAK,OAAO,WAAW,YAAY;AAEzD,cAAI,CAAC,eAAe;AAClB,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,cACAC;AAAA,YACF;AAAA,UACF;AAEA,cAAI,cAAc,mCAAgC;AAChD,oBAAQ,MAAM,oDAAoD;AAClE,mBAAO;AAAA,cACL;AAAA,cACA;AAAA,cACAA;AAAA,YACF;AAAA,UACF;AAEA,yBAAe;AAAA,QACjB;AAEA,QAAAD,MAAK,YAAY,YAAY;AAAA,MAC/B;AAEA,aAAO,YAAY,OAAO,oBAA2BC,SAAe;AAAA,IACtE;AAEA,QAAI,eAAe;AAEnB,QAAI,GAAG,YAAY,CAAC,QAA8B;AAChD,YAAM,iBAA2B,CAAC;AAClC,UAAI,eAAe;AAEnB,UAAI,GAAG,QAAQ,CAAC,UAA2B;AACzC,YAAI,eAAe,eAAe;AAChC,gBAAM,MAAM,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AAC9D,yBAAe,KAAK,GAAG;AACvB,0BAAgB,IAAI;AAAA,QACtB;AAAA,MACF,CAAC;AAED,UAAI,GAAG,OAAO,MAAM;AAClB,YAAI,aAAc;AAClB,uBAAe;AAEf,cAAM,UAAU,KAAK,IAAI;AACzB,cAAM,WAAW,UAAU;AAE3B,cAAM,kBAA0C,CAAC;AAEjD,YAAI,IAAI,SAAS;AACf,qBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,gBAAI,OAAO;AACT,8BAAgB,IAAI,YAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,IACpD,MAAM,KAAK,IAAI,IACf;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAEA,cAAM,cAAc,gBAAgB,cAAc,KAAK;AACvD,YAAI;AAEJ,YAAI,eAAe,SAAS,GAAG;AAC7B,cAAI,oBAAoB,WAAW,GAAG;AACpC,8BAAkB,iBAAiB,WAAW;AAAA,UAChD,OAAO;AACL,kBAAM,OAAO,OAAO,OAAO,cAAc;AACzC,8BACE,KAAK,SAAS,gBACV,KAAK,SAAS,SAAS,GAAG,aAAa,IAAI,mBAC3C,KAAK,SAAS,OAAO;AAAA,UAC7B;AAAA,QACF;AAEA,cAAM,eAAe;AAAA,UACnB;AAAA,UACAD,MAAK,QAAQ;AAAA,QACf;AAEA,cAAM,aAAa,IAAI,cAAc;AAErC,YAAI,gBAAkC;AAAA,UACpC,IAAI;AAAA,UACJ;AAAA,UACA,WAAWA,MAAK,aAAa;AAAA,UAC7B,WAAW;AAAA,UACX;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,UACR,YAAY,IAAI,iBAAiB;AAAA,UACjC,SAAS,uBAAuB,eAAe;AAAA,UAC/C,MAAM;AAAA,UACN;AAAA,UACA,cAAc,cAAc,QAAQ;AAAA,UACpC,YAAY;AAAA,UACZ,IAAI,cAAc,OAAO,aAAa;AAAA,QACxC;AAEA,YAAIA,MAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgBA,MAAK,OAAO,WAAW,aAAa;AAE1D,cAAI,CAAC,cAAe;AAEpB,cAAI,cAAc,qCAAiC;AACjD,oBAAQ,MAAM,oDAAoD;AAClE;AAAA,UACF;AAEA,0BAAgB;AAAA,QAClB;AAEA,QAAAA,MAAK,YAAY,aAAa;AAAA,MAChC,CAAC;AAAA,IACH,CAAC;AAED,QAAI,GAAG,SAAS,CAAC,QAAe;AAC9B,UAAI,aAAc;AAClB,qBAAe;AAEf,UAAI,aAAgC;AAAA,QAClC,IAAI;AAAA,QACJ;AAAA,QACA,WAAWA,MAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,IAAI;AAAA,QACpB;AAAA,QACA;AAAA,QACA,cAAc,IAAI,WAAW;AAAA,QAC7B,OAAO,IAAI;AAAA,MACb;AAEA,UAAIA,MAAK,QAAQ,YAAY;AAC3B,cAAM,gBAAgBA,MAAK,OAAO,WAAW,UAAU;AAEvD,YACE,kBACC,cAAc,iCACb,cAAc,gCAChB;AACA,uBAAa;AAAA,QACf;AAAA,MACF;AAEA,MAAAA,MAAK,YAAY,UAAU;AAAA,IAC7B,CAAC;AAED,QAAI,GAAG,WAAW,MAAM;AACtB,UAAI,aAAc;AAClB,qBAAe;AAEf,UAAI,aAAgC;AAAA,QAClC,IAAI;AAAA,QACJ;AAAA,QACA,WAAWA,MAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,IAAI;AAAA,QACpB;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB;AAEA,UAAIA,MAAK,QAAQ,YAAY;AAC3B,cAAM,gBAAgBA,MAAK,OAAO,WAAW,UAAU;AAEvD,YACE,kBACC,cAAc,iCACb,cAAc,gCAChB;AACA,uBAAa;AAAA,QACf;AAAA,MACF;AAEA,MAAAA,MAAK,YAAY,UAAU;AAAA,IAC7B,CAAC;AAED,QAAI,GAAG,SAAS,MAAM;AACpB,UAAI,aAAc;AAClB,UAAI,CAAC,IAAI,UAAW;AAEpB,qBAAe;AAEf,UAAI,aAAgC;AAAA,QAClC,IAAI;AAAA,QACJ;AAAA,QACA,WAAWA,MAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,IAAI;AAAA,QACpB;AAAA,QACA;AAAA,QACA,cAAc;AAAA,MAChB;AAEA,UAAIA,MAAK,QAAQ,YAAY;AAC3B,cAAM,gBAAgBA,MAAK,OAAO,WAAW,UAAU;AACvD,YACE,kBACC,cAAc,iCACb,cAAc,gCAChB;AACA,uBAAa;AAAA,QACf;AAAA,MACF;AAEA,MAAAA,MAAK,YAAY,UAAU;AAAA,IAC7B,CAAC;AAED,WAAO;AAAA,EACT;AAAA,EAEA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS;AACjB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,yCAAyC;AAAA,MACxD;AACA;AAAA,IACF;AAEA,SAAK,UAAU;AAEf,QAAI,KAAK,cAAc,KAAK,qBAAqB;AAC/C,WAAK,WAAW,UAAU,KAAK;AAAA,IACjC;AAEA,QAAI,KAAK,cAAc,KAAK,iBAAiB;AAC3C,WAAK,WAAW,MAAM,KAAK;AAAA,IAC7B;AAEA,QAAI,KAAK,eAAe,KAAK,sBAAsB;AACjD,WAAK,YAAY,UAAU,KAAK;AAAA,IAClC;AAEA,QAAI,KAAK,eAAe,KAAK,kBAAkB;AAC7C,WAAK,YAAY,MAAM,KAAK;AAAA,IAC9B;AAAA,EACF;AACF;;;ACzdO,IAAM,oBAAN,MAAwB;AAAA,EACrB;AAAA,EACA;AAAA,EAEA,SAAiC;AAAA,EACjC,UAAU;AAAA,EAEV,WAAW,oBAAI,IAA8B;AAAA,EAC7C,qBAAqB,oBAAI,QAA8B;AAAA,EACvD,qBAAqB;AAAA,EAErB,gBAAuD;AAAA,EAEvD,0BAA0B,oBAAI,IAAY;AAAA,EAC1C,4BAA4B;AAAA,EAE5B,eAAyC;AAAA,EAEzC,4BAEG;AAAA,EACH,+BAEG;AAAA,EAEH,kBAAsC,CAAC;AAAA,EAE/C,YACE,aACA,cACA;AACA,SAAK,cAAc;AACnB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,MAAM,QAA+B;AACnC,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,+CAA+C;AAAA,MAC9D;AAEA;AAAA,IACF;AAEA,SAAK,SAAS;AAEd,QAAI,CAAC,KAAK,YAAY,GAAG;AACvB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,2CAA2C;AAAA,MAC1D;AAEA;AAAA,IACF;AAEA,SAAK,gBAAgB,YAAY,MAAM;AACrC,WAAK,aAAa;AAAA,IACpB,GAAG,kBAAkB,oBAAoB;AAEzC,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,cAAuB;AAC7B,UAAM,YACJ,OAAO,WAAW,cACd,SACA,OAAO,WAAW,cAChB,SACA;AAER,QAAI,CAAC,UAAW,QAAO;AAEvB,UAAM,UAAU;AAChB,UAAM,eAAgB,UAAkB,OAAO;AAI/C,QAAI,cAAc;AAChB,WAAK,iBAAiB,YAAY;AAAA,IACpC,OAAO;AACL,WAAK,WAAW,WAAW,OAAO;AAAA,IACpC;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAiB,MAA+B;AACtD,SAAK,eAAe;AACpB,SAAK,4BAA4B,KAAK,mBAAmB,KAAK,IAAI;AAClE,SAAK,+BAA+B,KAAK,sBAAsB,KAAK,IAAI;AAExE,SAAK,oBAAoB,CAAC,YAAY,MAAM,kBAAkB;AAC5D,WAAK,4BAA4B,YAAY,MAAM,aAAa;AAChE,WAAK,sBAAsB,YAAY,IAAI;AAAA,IAC7C;AAEA,SAAK,uBAAuB,CAAC,YAAY,UAAU;AACjD,WAAK,+BAA+B,YAAY,KAAK;AACrD,WAAK,yBAAyB,YAAY,KAAK;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAAW,WAAgB,SAAuB;AACxD,UAAM,YAAY,oBAAI,IAAiB;AACvC,QAAI,oBAAoB;AAExB,UAAM,OAA0B;AAAA,MAC9B,eAAe;AAAA,MACf,QAAQ,CAAC,aAAa;AACpB,cAAM,KAAK,EAAE;AACb,kBAAU,IAAI,IAAI,QAAQ;AAC1B,eAAO;AAAA,MACT;AAAA,MACA,mBAAmB,CAAC,YAAY,MAAM,kBAAkB;AACtD,aAAK,sBAAsB,YAAY,IAAI;AAAA,MAC7C;AAAA,MACA,sBAAsB,CAAC,YAAY,UAAU;AAC3C,aAAK,yBAAyB,YAAY,KAAK;AAAA,MACjD;AAAA,IACF;AAEA,cAAU,OAAO,IAAI;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBACN,aACA,MACM;AACN,SAAK,wBAAwB,MAAM;AACnC,SAAK,4BAA4B;AAEjC,QAAI;AACF,WAAK,wBAAwB,KAAK,OAAO;AACzC,WAAK,cAAc,KAAK,SAAS,MAAM,CAAC;AAAA,IAC1C,SAAS,OAAO;AACd,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,4CAA4C,KAAK;AAAA,MAChE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,wBAAwB,OAAkC;AAChE,QAAI,CAAC,MAAO;AAEZ,QAAI,KAAK,gBAAgB,KAAK,KAAK,KAAK,eAAe,KAAK,GAAG;AAC7D,WAAK;AAAA,IACP;AAEA,SAAK,wBAAwB,MAAM,KAAK;AACxC,SAAK,wBAAwB,MAAM,OAAO;AAAA,EAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,yBACN,aACA,OACM;AACN,QAAI,CAAC,KAAK,gBAAgB,KAAK,EAAG;AAElC,UAAM,cAAc,KAAK,mBAAmB,IAAI,KAAK;AACrD,QAAI,CAAC,YAAa;AAElB,UAAM,UAAU,KAAK,SAAS,IAAI,WAAW;AAC7C,QAAI,SAAS;AACX,cAAQ,cAAc,KAAK,IAAI;AAC/B,WAAK,gBAAgB,KAAK,OAAO;AACjC,WAAK,SAAS,OAAO,WAAW;AAAA,IAClC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,cACN,OACA,mBACA,OACM;AACN,QAAI,CAAC,MAAO;AAEZ,QAAI,kBAAkB;AAEtB,QAAI,KAAK,gBAAgB,KAAK,KAAK,KAAK,eAAe,KAAK,GAAG;AAC7D,YAAM,cAAc,KAAK,uBAAuB,KAAK;AACrD,WAAK,iBAAiB,OAAO,aAAa,mBAAmB,KAAK;AAClE,WAAK,wBAAwB,IAAI,WAAW;AAC5C,wBAAkB;AAAA,IACpB;AAEA,SAAK,cAAc,MAAM,OAAO,iBAAiB,QAAQ,CAAC;AAC1D,SAAK,cAAc,MAAM,SAAS,mBAAmB,KAAK;AAAA,EAC5D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,iBACN,OACA,aACA,mBACA,OACM;AACN,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,QAAQ,KAAK,iBAAiB,OAAO,iBAAiB;AAE5D,UAAM,aACJ,KAAK,4BAA4B,IAC7B,IAAI,KAAK,4BACT;AAEN,QAAI,UAAU,KAAK,SAAS,IAAI,WAAW;AAE3C,QAAI,CAAC,SAAS;AACZ,gBAAU;AAAA,QACR,IAAI,iBAAiB;AAAA,QACrB;AAAA,QACA,eAAe,KAAK,iBAAiB,KAAK;AAAA,QAC1C,eAAe,KAAK,iBAAiB,KAAK;AAAA,QAC1C,WAAW;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,qBAAqB;AAAA,QACrB,qBAAqB;AAAA,QACrB,gBAAgB,0BAA0B;AAAA,QAC1C,qBAAqB,0BAA0B;AAAA,QAC/C,wBAAwB;AAAA,QACxB,uBAAuB;AAAA,QACvB,cAAc;AAAA,QACd,cAAc,oBAAI,IAAI;AAAA,QACtB;AAAA,QACA,cAAc;AAAA;AAAA,QAEd,iBAAiB,2BAA2B;AAAA,QAC5C,iBAAiB,CAAC;AAAA,MACpB;AACA,WAAK,SAAS,IAAI,aAAa,OAAO;AAAA,IACxC;AAEA,YAAQ;AACR,YAAQ,mBAAmB;AAE3B,YAAQ,eAAe,MAAM,IAAI;AACjC,YAAQ,oBAAoB,MAAM,IAAI;AAEtC,QAAI,MAAM,8CAAyC,MAAM,aAAa;AACpE,WAAK,sBAAsB,SAAS,MAAM,WAAW;AAAA,IACvD;AAEA,UAAM,gBAAgB,wBAAwB;AAE9C,QAAI,eAAe;AACjB,cAAQ,oBAAoB;AAAA,IAC9B;AAEA,QAAI,mBAAmB;AACrB,YAAM,SAAS,QAAQ,aAAa,IAAI,iBAAiB,KAAK,KAAK;AACnE,cAAQ,aAAa,IAAI,mBAAmB,KAAK;AAEjD,UACE,CAAC,QAAQ,mBACT,SAAS,QAAQ,aAAa,IAAI,QAAQ,eAAe,KAAK,IAC9D;AACA,gBAAQ,kBAAkB;AAAA,MAC5B;AAAA,IACF;AAEA,YAAQ,QAAQ;AAEhB,UAAM,cAAc,MAAM,kBAAkB;AAC5C,QAAI,QAAQ,sBAAsB,aAAa;AAC7C,cAAQ,sBAAsB;AAC9B,cAAQ,sBAAsB;AAAA,IAChC,OAAO;AACL,cAAQ;AAAA,IACV;AAEA,SAAK,qBAAqB,OAAO;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBACN,SACA,SACM;AACN,UAAM,QAAQ,QAAQ;AAEtB,eAAW,UAAU,SAAS;AAC5B,UACE,MAAM,YAAY,QAAQ,kBAAkB,0BAC5C,CAAC,MAAM,YAAY,IAAI,OAAO,GAAG,GACjC;AACA;AAAA,MACF;AAEA,YAAM,YAAY;AAAA,QAChB,OAAO;AAAA,SACN,MAAM,YAAY,IAAI,OAAO,GAAG,KAAK,KAAK;AAAA,MAC7C;AAEA,UAAI,OAAO,eAAe;AACxB,cAAM,mBAAmB;AAAA,UACvB,OAAO;AAAA,WACN,MAAM,mBAAmB,IAAI,OAAO,GAAG,KAAK,KAAK;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAEA,QACE,QAAQ,gBAAgB,SACxB,kBAAkB,+BAClB;AACA,cAAQ,gBAAgB;AAAA,QACtB,GAAG,QAAQ;AAAA,UACT;AAAA,UACA,kBAAkB,gCAChB,QAAQ,gBAAgB;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,wBACN,SACgC;AAChC,UAAM,QAAQ,QAAQ;AAEtB,QAAI,MAAM,YAAY,SAAS,GAAG;AAChC,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,MAAM,KAAK,MAAM,YAAY,QAAQ,CAAC,EAClD,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,MAAM,GAAG,kBAAkB,mBAAmB;AAEjD,UAAM,kBAAkB,OAAO,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AACnD,YAAM,eAAe,MAAM,mBAAmB,IAAI,GAAG,KAAK;AAC1D,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,sBACE,QAAQ,IAAI,KAAK,MAAO,eAAe,QAAS,GAAG,IAAI;AAAA,MAC3D;AAAA,IACF,CAAC;AAED,WAAO,EAAE,gBAAgB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,SAAiC;AAC5D,UAAM,WAAW,KAAK,kBAAkB,OAAO;AAE/C,QAAI,WAAW,kBAAkB,cAAc;AAC7C,cAAQ,eAAe;AACvB,cAAQ,mBAAmB,yBAAyB,SAAS;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH,WAAW,QAAQ,eAAe,kBAAkB,mBAAmB;AACrE,cAAQ,eAAe;AACvB,cAAQ,mBAAmB,uBAAuB,QAAQ,YAAY;AAAA,IACxE,OAAO;AACL,cAAQ,eAAe;AACvB,cAAQ,mBAAmB;AAAA,IAC7B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAkB,SAAmC;AAC3D,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAY,MAAM,QAAQ;AAEhC,QAAI,YAAY,kBAAkB,oBAAoB;AACpD,aAAO;AAAA,IACT;AAEA,UAAM,oBAAoB,KAAK,IAAI,WAAW,GAAG;AACjD,WAAQ,QAAQ,sBAAsB,oBAAqB;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAqB;AAC3B,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,YAAwC,CAAC;AAE/C,eAAW,WAAW,KAAK,SAAS,OAAO,GAAG;AAC5C,YAAM,eACJ,QAAQ,eAAe,QAAQ;AAEjC,UACE,eAAe,kBAAkB,qBACjC,CAAC,QAAQ,cACT;AACA;AAAA,MACF;AAEA,YAAM,WAAW,KAAK,kBAAkB,OAAO;AAC/C,YAAM,UAAU,QAAQ,2BAA2B;AACnD,YAAM,kBACJ,QAAQ,kBAAkB,QAAQ;AAEpC,YAAM,cAAc,KAAK,wBAAwB,OAAO;AAExD,gBAAU,KAAK;AAAA,QACb,IAAI,QAAQ;AAAA,QACZ,aAAa,QAAQ;AAAA,QACrB,eAAe,QAAQ;AAAA,QACvB,eAAe,QAAQ;AAAA,QACvB,cAAc,QAAQ;AAAA,QACtB,iBAAiB,QAAQ;AAAA,QACzB,eAAe,QAAQ,kBAAkB,QAAQ;AAAA,QACjD;AAAA,QACA;AAAA,QACA,gBAAgB;AAAA,QAChB,gBAAgB,EAAE,GAAG,QAAQ,eAAe;AAAA,QAC5C,qBAAqB,EAAE,GAAG,QAAQ,oBAAoB;AAAA,QACtD,mBAAmB,QAAQ;AAAA,QAC3B,OAAO,QAAQ;AAAA,QACf,mBAAmB,QAAQ;AAAA,QAC3B,cAAc,QAAQ;AAAA,QACtB,kBAAkB,QAAQ;AAAA,QAC1B,aAAa;AAAA,QACb,WAAW,QAAQ;AAAA,QACnB;AAAA,MACF,CAAC;AAED,cAAQ,yBAAyB,QAAQ;AACzC,cAAQ,wBAAwB,QAAQ;AACxC,cAAQ,eAAe;AACvB,cAAQ,sBAAsB,0BAA0B;AACxD,cAAQ,kBAAkB,CAAC;AAAA,IAC7B;AAEA,eAAW,WAAW,KAAK,iBAAiB;AAC1C,YAAM,cAAc,KAAK,wBAAwB,OAAO;AAExD,gBAAU,KAAK;AAAA,QACb,IAAI,QAAQ;AAAA,QACZ,aAAa,QAAQ;AAAA,QACrB,eAAe,QAAQ;AAAA,QACvB,eAAe,QAAQ;AAAA,QACvB,cAAc,QAAQ;AAAA,QACtB,iBAAiB,QAAQ;AAAA,QACzB,eACE,QAAQ,kBAAkB,KAAK,IAAI,QAAQ,cAAc,CAAC;AAAA,QAC5D,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,gBAAgB,EAAE,GAAG,QAAQ,eAAe;AAAA,QAC5C,qBAAqB,0BAA0B;AAAA,QAC/C,mBAAmB,QAAQ;AAAA,QAC3B,OAAO,QAAQ;AAAA,QACf,mBAAmB,QAAQ;AAAA,QAC3B,cAAc,QAAQ;AAAA,QACtB,kBAAkB,QAAQ;AAAA,QAC1B;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,aAAa,QAAQ;AAAA,QACrB;AAAA,MACF,CAAC;AAAA,IACH;AACA,SAAK,kBAAkB,CAAC;AAExB,QAAI,UAAU,WAAW,EAAG;AAE5B,QAAI,UAA4B;AAAA,MAC9B,OAAO;AAAA,MACP,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW;AAAA,MACX,UAAU;AAAA,IACZ;AAEA,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,WAAW,KAAK,OAAO,WAAW,OAAO;AAC/C,UAAI,CAAC,SAAU;AACf,gBAAU;AAAA,IACZ;AAEA,SAAK,YAAY,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,iBACN,OACA,mBAMA;AACA,UAAM,YAAY,MAAM;AAExB,QAAI,CAAC,WAAW;AACd,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QACE,qBACA,KAAK,wBAAwB,IAAI,iBAAiB,GAClD;AACA,YAAM,YAAY,UAAU;AAC5B,YAAM,YAAY,MAAM;AACxB,YAAM,eAAe,cAAc;AAEnC,UAAI,cAAc;AAChB,cAAM,cAAc,KAAK,UAAU,WAAW,SAAS;AAEvD,eAAO;AAAA,UACL;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,WAAW;AAAA,MACb;AAAA,IACF;AAEA,QAAI,MAAM,kBAAkB,UAAU,eAAe;AACnD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,kBAAkB,UAAU,eAAe;AACnD,aAAO;AAAA,QACL;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,UACN,WACA,WACoB;AACpB,QAAI,CAAC,aAAa,CAAC,WAAW;AAC5B,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,UAA8B,CAAC;AACrC,UAAM,UAAU,oBAAI,IAAI;AAAA,MACtB,GAAG,OAAO,KAAK,SAAS;AAAA,MACxB,GAAG,OAAO,KAAK,SAAS;AAAA,IAC1B,CAAC;AAED,UAAM,WAAW,oBAAI,IAAI,CAAC,YAAY,OAAO,KAAK,CAAC;AAEnD,eAAW,OAAO,SAAS;AACzB,UAAI,SAAS,IAAI,GAAG,EAAG;AAEvB,YAAM,YAAY,UAAU,GAAG;AAC/B,YAAM,YAAY,UAAU,GAAG;AAE/B,UAAI,cAAc,WAAW;AAC3B;AAAA,MACF;AAEA,YAAM,gBAAgB,KAAK,eAAe,WAAW,SAAS;AAE9D,cAAQ,KAAK,EAAE,KAAK,cAAc,CAAC;AAEnC,UAAI,QAAQ,UAAU,IAAI;AACxB;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,eAAe,GAAQ,GAAiB;AAC9C,QAAI,MAAM,EAAG,QAAO;AAEpB,QAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAElC,QAAI,MAAM,QAAQ,MAAM,KAAM,QAAO;AAErC,QAAI,OAAO,MAAM,cAAc,OAAO,MAAM,YAAY;AACtD,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,QAAQ,CAAC,KAAK,MAAM,QAAQ,CAAC,GAAG;AACxC,UAAI,EAAE,WAAW,EAAE,OAAQ,QAAO;AAClC,eAAS,IAAI,GAAG,IAAI,EAAE,QAAQ,KAAK;AACjC,YAAI,EAAE,CAAC,MAAM,EAAE,CAAC,EAAG,QAAO;AAAA,MAC5B;AACA,aAAO;AAAA,IACT;AAEA,QAAI,OAAO,MAAM,YAAY,OAAO,MAAM,UAAU;AAClD,YAAM,QAAQ,OAAO,KAAK,CAAC;AAC3B,YAAM,QAAQ,OAAO,KAAK,CAAC;AAE3B,UAAI,MAAM,WAAW,MAAM,OAAQ,QAAO;AAE1C,iBAAW,OAAO,OAAO;AACvB,YAAI,EAAE,GAAG,MAAM,EAAE,GAAG,EAAG,QAAO;AAAA,MAChC;AACA,aAAO;AAAA,IACT;AAEA,WAAO,MAAM;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,gBAAgB,OAA8B;AACpD,UAAM,MAAM,MAAM;AAClB,WACE,qCACA,kCACA,+BACA,kCACA;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,eAAe,OAA8B;AACnD,YAAQ,MAAM,mCAAsC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,uBAAuB,OAA6B;AAC1D,QAAI,KAAK,KAAK,mBAAmB,IAAI,KAAK;AAC1C,QAAI,GAAI,QAAO;AAEf,QAAI,MAAM,WAAW;AACnB,WAAK,KAAK,mBAAmB,IAAI,MAAM,SAAS;AAChD,UAAI,IAAI;AACN,aAAK,mBAAmB,IAAI,OAAO,EAAE;AACrC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,SAAK,KAAK,EAAE,KAAK,kBAAkB;AACnC,SAAK,mBAAmB,IAAI,OAAO,EAAE;AACrC,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAiB,OAA6B;AACpD,UAAM,OAAO,MAAM;AACnB,QAAI,CAAC,KAAM,QAAO;AAElB,QAAI,OAAO,SAAS,YAAY;AAC9B,aAAO,KAAK,eAAe,KAAK,QAAQ;AAAA,IAC1C;AAEA,QAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,UAAI,KAAK,YAAa,QAAO,KAAK;AAClC,UAAI,KAAK;AACP,eAAO,KAAK,OAAO,eAAe,KAAK,OAAO,QAAQ;AACxD,UAAI,KAAK,MAAM;AACb,cAAM,QAAQ,KAAK;AACnB,eAAO,MAAM,eAAe,MAAM,QAAQ;AAAA,MAC5C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAiB,OAAoC;AAC3D,YAAQ,MAAM,KAAK;AAAA,MACjB;AACE,eAAO;AAAA,MACT;AACE,eAAO;AAAA,MACT;AACE,eAAO;AAAA,MACT;AAAA,MACA;AACE,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkB;AAChB,SAAK,aAAa;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,aAAmD;AAC5D,WAAO,KAAK,SAAS,IAAI,WAAW;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,0BAA8C;AAC5C,WAAO,MAAM,KAAK,KAAK,SAAS,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY;AAAA,EACxE;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,aAAa;AAElB,QAAI,KAAK,eAAe;AACtB,oBAAc,KAAK,aAAa;AAChC,WAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,KAAK,cAAc;AACrB,UAAI,KAAK,2BAA2B;AAClC,aAAK,aAAa,oBAAoB,KAAK;AAAA,MAC7C;AACA,UAAI,KAAK,8BAA8B;AACrC,aAAK,aAAa,uBAChB,KAAK;AAAA,MACT;AAAA,IACF;AAEA,SAAK,eAAe;AACpB,SAAK,4BAA4B;AACjC,SAAK,+BAA+B;AACpC,SAAK,SAAS,MAAM;AACpB,SAAK,kBAAkB,CAAC;AACxB,SAAK,wBAAwB,MAAM;AACnC,SAAK,qBAAqB;AAC1B,SAAK,SAAS;AACd,SAAK,UAAU;AAAA,EACjB;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAsB;AACpB,SAAK,SAAS,MAAM;AACpB,SAAK,qBAAqB,oBAAI,QAA8B;AAC5D,SAAK,kBAAkB,CAAC;AACxB,SAAK,wBAAwB,MAAM;AACnC,SAAK,qBAAqB;AAAA,EAC5B;AACF;;;AC31BO,IAAM,mBAAN,MAAuB;AAAA,EAU5B,YACU,aACA,cACR;AAFQ;AACA;AAAA,EACP;AAAA,EAZK,UAAU;AAAA,EACV,SAAiC;AAAA,EACjC,UAAU;AAAA,EAEV,2BAA4D;AAAA,EAC5D,4BAEG;AAAA,EAOX,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,8CAA8C;AAAA,MAC7D;AACA;AAAA,IACF;AAEA,QAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,IAAI;AACjD;AAAA,IACF;AAEA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,SAAK,2BAA2B,CAAC,UAAiB;AAChD,WAAK,eAAe,OAAO,mBAAmB;AAG9C,iBAAW,MAAM;AACf,gBAAQ,KAAK,CAAC;AAAA,MAChB,GAAG,GAAG;AAAA,IACR;AAEA,SAAK,4BAA4B,CAAC,WAAoB;AACpD,YAAM,QACJ,kBAAkB,QAAQ,SAAS,IAAI,MAAM,OAAO,MAAM,CAAC;AAC7D,WAAK,eAAe,OAAO,oBAAoB;AAAA,IACjD;AAEA,YAAQ,GAAG,qBAAqB,KAAK,wBAAwB;AAC7D,YAAQ,GAAG,sBAAsB,KAAK,yBAAyB;AAAA,EACjE;AAAA,EAEA,UAAU;AACR,QAAI,CAAC,KAAK,QAAS;AAEnB,SAAK,UAAU;AAEf,QAAI,KAAK,0BAA0B;AACjC,cAAQ;AAAA,QACN;AAAA,QACA,KAAK;AAAA,MACP;AACA,WAAK,2BAA2B;AAAA,IAClC;AAEA,QAAI,KAAK,2BAA2B;AAClC,cAAQ;AAAA,QACN;AAAA,QACA,KAAK;AAAA,MACP;AACA,WAAK,4BAA4B;AAAA,IACnC;AAEA,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,eAAe,OAAc,QAAgB;AACnD,UAAM,YAAY,KAAK,aAAa;AAEpC,UAAM,QAA0B;AAAA,MAC9B,IAAI,GAAG,SAAS,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,SAAS;AAAA,MAChD,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,CAAC,cAAc,IAAI,MAAM,KAAK,MAAM,OAAO,EAAE,CAAC;AAAA,MACpD,YAAY,MAAM;AAAA,IACpB;AAEA,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,WAAW,KAAK,OAAO,WAAW,KAAK;AAE7C,UAAI,CAAC,SAAU;AAAA,IACjB;AAEA,SAAK,YAAY,KAAK;AAAA,EACxB;AACF;;;AClGO,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EACA;AAAA,EAEA,SAAuC,oBAAI,IAAI;AAAA,EAC/C,SAAiC;AAAA,EAEzC,YACE,aACA,cACA;AACA,SAAK,cAAc;AACnB,SAAK,eAAe;AAAA,EACtB;AAAA,EAEA,MAAM,QAA+B;AACnC,SAAK,SAAS;AAEd,QAAI,CAAC,OAAO,OAAQ;AACpB,QAAI,OAAO,yBAAyB,MAAO;AAE3C,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AACzD,WAAK,cAAc,MAAM,KAAK;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc,MAAc,OAAsB;AAChD,QAAI,KAAK,OAAO,IAAI,IAAI,GAAG;AACzB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,sBAAsB,IAAI,sBAAsB;AAAA,MAC/D;AAEA;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,cAAc,KAAK;AAExC,QAAI,CAAC,SAAS;AAEZ,cAAQ;AAAA,QACN,gDAAgD,IAAI;AAAA,MACtD;AACA;AAAA,IACF;AAEA,UAAM,QAAQ,KAAK,SAAS,KAAK;AAEjC,UAAM,YAA4B;AAAA,MAChC;AAAA,MACA,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK,IAAI;AAAA,MACpB,MAAM;AAAA,QACJ,SAAS;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,SAAK,UAAU,SAAS;AAExB,UAAM,cAAc,KAAK,UAAU,OAAO,SAAS,IAAI;AAEvD,SAAK,OAAO,IAAI,MAAM,EAAE,MAAM,SAAS,YAAY,CAAC;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,MAAoB;AAClC,UAAM,QAAQ,KAAK,OAAO,IAAI,IAAI;AAClC,QAAI,OAAO;AACT,YAAM,YAAY;AAClB,WAAK,OAAO,OAAO,IAAI;AAAA,IACzB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,UAAU,OAAgD;AAChE,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,gBAAgB,KAAK,OAAO,WAAW,KAAK;AAElD,UAAI,CAAC,eAAe;AAClB;AAAA,MACF;AAEA,UACE,cAAc,qCACd,cAAc,uCACd;AAEA,gBAAQ,MAAM,oDAAoD;AAClE;AAAA,MACF;AAEA,WAAK,YAAY,aAAa;AAAA,IAChC,OAAO;AACL,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,cAAc,OAAqC;AACzD,QAAI,CAAC,SAAU,OAAO,UAAU,cAAc,OAAO,UAAU,UAAW;AACxE,aAAO;AAAA,IACT;AAGA,QACE,OAAO,UAAU,YACjB,cAAc,SACd,cAAc,SACd,eAAe,SACf,OAAQ,MAAc,aAAa,YACnC;AACA;AAAA,IACF;AAGA,QACE,OAAO,UAAU,cACjB,cAAc,SACd,eAAe,SACf,OAAQ,MAAc,aAAa,YACnC;AACA;AAAA,IACF;AAGA,QACE,OAAO,UAAU,YACjB,cAAc,SACd,cAAc,SACd,eAAe,SACf,EAAE,cAAc,QAChB;AACA;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,SAAS,OAAyB;AACxC,UAAM,WAAW;AACjB,WAAO,SAAS,SAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,UACN,OACA,SACA,WACY;AACZ,UAAM,WAAW;AAEjB,QAAI,qCAAkC;AACpC,aAAO,KAAK,iBAAiB,UAAU,SAAS;AAAA,IAClD,OAAO;AACL,aAAO,KAAK,eAAe,UAAU,SAAS;AAAA,IAChD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,iBAAiB,OAAY,WAA+B;AAClE,WAAO,MAAM,UAAU,CAAC,OAAgB,cAAuB;AAC7D,YAAM,SAAS,KAAK,mBAAmB,OAAO,SAAS;AACvD,YAAM,aAAa,KAAK,kBAAkB;AAE1C,YAAM,cAAgC;AAAA,QACpC;AAAA,QACA,WAAW,KAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,IAAI;AAAA,QACpB,MAAM;AAAA,UACJ,SAAS;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAEA,WAAK,UAAU,WAAW;AAAA,IAC5B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,eAAe,OAAY,WAA+B;AAChE,QAAI,aAA0B,EAAE,MAAM,SAAS;AAE/C,UAAM,mBAAmB,MAAM;AAC/B,UAAM,WAAW,CAAC,WAAgB;AAChC,mBAAa;AAAA,QACX,MAAM,QAAQ,QAAQ;AAAA,QACtB,SAAS,QAAQ;AAAA,MACnB;AACA,aAAO,iBAAiB,MAAM;AAAA,IAChC;AAEA,UAAM,cAAc,MAAM,UAAU,MAAM;AACxC,YAAM,WAAW,MAAM,SAAS;AAChC,YAAM,aAAa,KAAK,kBAAkB;AAE1C,YAAM,cAAgC;AAAA,QACpC;AAAA,QACA,WAAW,KAAK,aAAa;AAAA,QAC7B,WAAW,KAAK,IAAI;AAAA,QACpB,MAAM;AAAA,UACJ,SAAS;AAAA,UACT;AAAA,UACA,OAAO;AAAA,UACP,QAAQ;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAEA,WAAK,UAAU,WAAW;AAAA,IAC5B,CAAC;AAED,WAAO,MAAM;AACX,kBAAY;AACZ,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,mBAAmB,OAAgB,WAAiC;AAC1E,UAAM,aAAa,KAAK,qBAAqB,KAAK,kBAAkB,CAAC;AACrE,UAAM,UAAU,KAAK,oBAAoB,OAAO,SAAS;AAEzD,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,qBAAqB,OAAwB;AACnD,QAAI,CAAC,MAAO,QAAO;AAEnB,UAAM,QAAQ,MAAM,MAAM,IAAI;AAE9B,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,sBAAsB,EAAG;AAC3C,UAAI,KAAK,SAAS,oBAAoB,EAAG;AACzC,UAAI,KAAK,SAAS,kBAAkB,EAAG;AACvC,UAAI,KAAK,SAAS,WAAW,EAAG;AAGhC,YAAM,UACJ,KAAK,MAAM,8BAA8B,KACzC,KAAK,MAAM,iBAAiB,KAC5B,KAAK,MAAM,YAAY;AAGzB,YAAM,cAAc,KAAK,MAAM,SAAS;AAExC,YAAM,QAAQ,WAAW;AAEzB,UAAI,SAAS,MAAM,CAAC,GAAG;AACrB,cAAM,OAAO,MAAM,CAAC;AACpB,YACE,CAAC;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,SAAS,IAAI,GACf;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,oBAAoB,OAAgB,WAA6B;AACvE,QACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAO,cAAc,YACrB,cAAc,MACd;AACA,aAAO;AAAA,IACT;AAEA,UAAM,UAAmC,CAAC;AAC1C,UAAM,WAAW;AACjB,UAAM,UAAU;AAEhB,eAAW,OAAO,OAAO,KAAK,QAAQ,GAAG;AACvC,UAAI,SAAS,GAAG,MAAM,QAAQ,GAAG,GAAG;AAClC,gBAAQ,GAAG,IAAI,SAAS,GAAG;AAAA,MAC7B;AAAA,IACF;AAEA,QAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;AACrC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAwC;AAC9C,QAAI;AACF,YAAM,MAAM,IAAI,MAAM;AACtB,aAAO,IAAI;AAAA,IACb,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,eAAW,CAAC,EAAE,KAAK,KAAK,KAAK,QAAQ;AACnC,YAAM,YAAY;AAAA,IACpB;AACA,SAAK,OAAO,MAAM;AAAA,EACpB;AACF;;;AC1WO,IAAM,gBAAN,MAAoB;AAAA,EAIzB,YACU,aACA,cACR;AAFQ;AACA;AAAA,EAGV;AAAA,EARQ,kBAAkB,oBAAI,IAA4B;AAAA,EAClD,SAAiC;AAAA;AAAA;AAAA;AAAA;AAAA,EAazC,UAAU,QAAgC;AACxC,SAAK,SAAS;AAAA,EAChB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,aAAa,QAAqC;AAChD,UAAM,YAAY,kBAAkB;AACpC,UAAM,YAAY,KAAK,IAAI;AAE3B,SAAK,gBAAgB,IAAI,WAAW,EAAE,WAAW,OAAO,CAAC;AAEzD,QAAI,kBAAkB,OAAO;AAE7B,QAAI,OAAO,WAAW,CAAC,OAAO,MAAM;AAClC,wBAAkB,KAAK,UAAU;AAAA,QAC/B,eAAe,OAAO,QAAQ;AAAA,QAC9B,WAAW,OAAO,QAAQ;AAAA,QAC1B,OAAO,OAAO,QAAQ;AAAA,MACxB,CAAC;AAAA,IACH;AAEA,UAAM,SAAU,OAAO,QAAQ,YAAY,KAAK;AAChD,UAAM,UAAU,OAAO,WAAW,CAAC;AAEnC,UAAM,cAAc;AAAA,MAClB,OAAO,oBAAoB,WACvB,kBACA,KAAK,UAAU,eAAe;AAAA,MAClC,KAAK,QAAQ;AAAA,IACf;AAEA,QAAI,eAA+B;AAAA,MACjC,IAAI;AAAA,MACJ,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,KAAK,OAAO;AAAA,MACZ;AAAA,MACA,SAAS,uBAAuB,OAAO;AAAA,MACvC,MAAM;AAAA,MACN,MAAM,OAAO,QAAQ,kBAAkB,OAAO,GAAG;AAAA,MACjD,WAAW;AAAA,MACX,aAAa,aAAa,QAAQ;AAAA,MAClC,SAAS,OAAO,UACZ;AAAA,QACE,eAAe,OAAO,QAAQ;AAAA,QAC9B,eAAe,uBAAuB,OAAO,QAAQ,aAAa;AAAA,QAClE,WAAW,OAAO,QAAQ;AAAA,QAC1B,OAAO,OAAO,QAAQ;AAAA,MACxB,IACA;AAAA,IACN;AAEA,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,gBAAgB,KAAK,OAAO,WAAW,YAAY;AAEzD,UAAI,CAAC,eAAe;AAClB,aAAK,gBAAgB,OAAO,SAAS;AACrC,eAAO;AAAA,MACT;AAEA,UAAI,cAAc,mCAAgC;AAChD,gBAAQ,MAAM,oDAAoD;AAClE,eAAO;AAAA,MACT;AAEA,qBAAe;AAAA,IACjB;AAEA,SAAK,YAAY,YAAY;AAE7B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,WAAmB,UAAsC;AAClE,UAAM,UAAU,KAAK,gBAAgB,IAAI,SAAS;AAElD,QAAI,CAAC,SAAS;AACZ,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ;AAAA,UACN,gDAAgD,SAAS;AAAA,QAC3D;AAAA,MACF;AACA;AAAA,IACF;AAEA,SAAK,gBAAgB,OAAO,SAAS;AAErC,UAAM,UAAU,KAAK,IAAI;AACzB,UAAM,WAAW,UAAU,QAAQ;AAEnC,UAAM,kBAAkB,SAAS,WAAW,CAAC;AAC7C,UAAM,eAAe;AAAA,MACnB,OAAO,SAAS,SAAS,WACrB,SAAS,OACT,KAAK,UAAU,SAAS,IAAI;AAAA,MAChC,KAAK,QAAQ;AAAA,IACf;AAEA,QAAI,gBAAiC;AAAA,MACnC,IAAI;AAAA,MACJ,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,QAAQ,SAAS;AAAA,MACjB,YAAY,SAAS,cAAc;AAAA,MACnC,SAAS,uBAAuB,eAAe;AAAA,MAC/C,MAAM;AAAA,MACN;AAAA,MACA,cAAc,cAAc,QAAQ;AAAA,MACpC,YAAY;AAAA,MACZ,IAAI,SAAS,UAAU,OAAO,SAAS,SAAS;AAAA,IAClD;AAEA,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,gBAAgB,KAAK,OAAO,WAAW,aAAa;AAE1D,UAAI,CAAC,eAAe;AAClB;AAAA,MACF;AAEA,UAAI,cAAc,qCAAiC;AACjD,gBAAQ,MAAM,oDAAoD;AAClE;AAAA,MACF;AAEA,sBAAgB;AAAA,IAClB;AAEA,SAAK,YAAY,aAAa;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,WAAmB,OAAsB;AACnD,UAAM,UAAU,KAAK,gBAAgB,IAAI,SAAS;AAElD,QAAI,CAAC,SAAS;AACZ,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ;AAAA,UACN,gDAAgD,SAAS;AAAA,QAC3D;AAAA,MACF;AACA;AAAA,IACF;AAEA,SAAK,gBAAgB,OAAO,SAAS;AAErC,UAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1E,UAAM,aAAa,iBAAiB,QAAQ,MAAM,QAAQ;AAE1D,QAAI,aAAgC;AAAA,MAClC,IAAI;AAAA,MACJ,WAAW,KAAK,aAAa;AAAA,MAC7B,WAAW,KAAK,IAAI;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAEA,QAAI,KAAK,QAAQ,YAAY;AAC3B,YAAM,gBAAgB,KAAK,OAAO,WAAW,UAAU;AAEvD,UAAI,iBAAiB,cAAc,+BAA8B;AAC/D,qBAAa;AAAA,MACf;AAAA,IACF;AAEA,SAAK,YAAY,UAAU;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU;AACR,SAAK,gBAAgB,MAAM;AAAA,EAC7B;AACF;;;ACtOO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACU,cAGA,aACA,WACR;AALQ;AAGA;AACA;AAAA,EAGV;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,SAAwB;AAC7B,UAAM,SAAS,KAAK,UAAU;AAE9B,QAAI,QAAQ,uBAAuB;AACjC,cAAQ,IAAI,iCAAiC,QAAQ,IAAI;AAAA,IAC3D;AAEA,YAAQ,QAAQ,MAAM;AAAA,MACpB;AACE,aAAK,aAAa,OAAO,cAAc;AACvC;AAAA,MAEF;AACE,YAAI,QAAQ,uBAAuB;AACjC,kBAAQ,KAAK,gCAAgC,QAAQ,IAAI;AAAA,QAC3D;AAAA,IACJ;AAEA,QAAI,QAAQ,IAAI;AACd,WAAK,YAAY;AAAA,QACf;AAAA,QACA,WAAW,QAAQ;AAAA,QACnB,MAAM,QAAQ;AAAA,QACd,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AClCA,IAAM,wBAAwB,KAAK;AAoB5B,IAAM,iBAAiB,CAC5B,KACA,KACA,aACA,cACA,QACA,YACG;AACH,QAAM,YAAY,kBAAkB;AACpC,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,cAAc,SAAS,eAAe;AAE5C,QAAM,kBAAkB,QAAQ,mBAAmB;AACnD,QAAM,kBAAkB,IAAI,QAAQ,eAAe;AACnD,QAAM,UAAU,mBAAmB,kBAAkB;AACrD,EAAC,IAAY,mBAAmB;AAEhC,QAAM,MAAM,IAAI,OAAO;AACvB,QAAM,UAAU,IAAI,UAAU,OAAO,YAAY;AAEjD,QAAM,UAAkC,CAAC;AAEzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,QAAI,OAAO;AACT,cAAQ,IAAI,YAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,IAC5C,MAAM,KAAK,IAAI,IACf;AAAA,IACN;AAAA,EACF;AAEA,MAAI,cAAc,cAAc,IAAI,MAAM,QAAQ,kBAAkB;AAEpE,MAAI,aAAa,OAAO,YAAY,IAAI,SAAS,aAAa;AAC5D,kBAAc;AAAA,MACZ,GAAG;AAAA,MACH,KAAK,YAAY,IAAI,MAAM,GAAG,WAAW,IAAI;AAAA,MAC7C,MAAM,YAAY;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,eAAiC;AAAA,IACnC,IAAI;AAAA,IACJ;AAAA,IACA,WAAW,aAAa;AAAA,IACxB,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,uBAAuB,OAAO;AAAA,IACvC,MAAM;AAAA,IACN,MAAM,IAAI,MAAM,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK;AAAA,IAC7D,WAAW;AAAA,IACX,aAAa,aAAa,QAAQ;AAAA,EACpC;AAEA,MAAI,QAAQ,YAAY;AACtB,UAAM,WAAW,OAAO,WAAW,YAAY;AAE/C,QAAI,CAAC,SAAU;AACf,QAAI,SAAS,mCAAgC;AAC3C,cAAQ,MAAM,oDAAoD;AAClE;AAAA,IACF;AAEA,mBAAe;AAAA,EACjB;AAEA,cAAY,YAAY;AAExB,QAAM,SAAmB,CAAC;AAC1B,MAAI,YAAY;AAChB,QAAM,gBAAgB,IAAI;AAC1B,QAAM,cAAc,IAAI;AAExB,MAAI,QAAQ,CAAC,UAAe,SAAyB;AACnD,QAAI,SAAS,OAAO,UAAU,cAAc,YAAY,aAAa;AACnE,YAAM,MAAM,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AAC9D,aAAO,KAAK,GAAG;AACf,mBAAa,IAAI;AAAA,IACnB;AAEA,WAAO,cAAc,MAAM,KAAK,CAAC,OAAO,GAAG,IAAI,CAAQ;AAAA,EACzD;AAEA,MAAI,MAAM,CAAC,UAAe,SAAgC;AACxD,QAAI,SAAS,OAAO,UAAU,cAAc,YAAY,aAAa;AACnE,YAAM,MAAM,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,KAAK;AAC9D,aAAO,KAAK,GAAG;AACf,mBAAa,IAAI;AAAA,IACnB;AAEA,WAAO,YAAY,MAAM,KAAK,CAAC,OAAO,GAAG,IAAI,CAAQ;AAAA,EACvD;AAEA,MAAI,GAAG,UAAU,MAAM;AACrB,UAAM,UAAU,KAAK,IAAI;AACzB,UAAM,WAAW,UAAU;AAE3B,UAAM,kBAA0C,CAAC;AACjD,UAAM,aAAa,IAAI,WAAW;AAElC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,UAAI,OAAO;AACT,wBAAgB,IAAI,YAAY,CAAC,IAAI,MAAM,QAAQ,KAAK,IACpD,MAAM,KAAK,IAAI,IACf,OAAO,KAAK;AAAA,MAClB;AAAA,IACF;AAEA,QAAI;AAEJ,QAAI,OAAO,SAAS,KAAK,CAAC,QAAQ,oBAAoB;AACpD,YAAM,OAAO,OAAO,OAAO,MAAM;AACjC,YAAM,UAAU,KAAK,SAAS,OAAO;AAErC,wBACE,QAAQ,SAAS,cACb,QAAQ,MAAM,GAAG,WAAW,IAAI,mBAChC;AAAA,IACR;AAEA,UAAM,eAAe;AAAA,MACnB;AAAA,MACA,QAAQ;AAAA,IACV;AAEA,QAAI,gBAAkC;AAAA,MACpC,IAAI;AAAA,MACJ;AAAA,MACA,WAAW,aAAa;AAAA,MACxB,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,QAAQ,IAAI;AAAA,MACZ,YAAY,IAAI,iBAAiB;AAAA,MACjC,SAAS,uBAAuB,eAAe;AAAA,MAC/C,MAAM;AAAA,MACN;AAAA,MACA,cAAc,cAAc,QAAQ;AAAA,MACpC,YAAY;AAAA,MACZ,IAAI,IAAI,cAAc,OAAO,IAAI,aAAa;AAAA,IAChD;AAEA,QAAI,QAAQ,YAAY;AACtB,YAAM,WAAW,OAAO,WAAW,aAAa;AAChD,UAAI,CAAC,SAAU;AAEf,UAAI,SAAS,qCAAiC;AAC5C,gBAAQ,MAAM,oDAAoD;AAClE;AAAA,MACF;AAEA,sBAAgB;AAAA,IAClB;AAEA,gBAAY,aAAa;AAAA,EAC3B,CAAC;AACH;AAeO,IAAM,uBAAuB,CAClC,aACA,cACA,WACA,YACG;AACH,SAAO,CACL,KACA,KACA,SACG;AACH,mBAAe,KAAK,KAAK,aAAa,cAAc,UAAU,GAAG,OAAO;AAExE,UAAM,UAAW,IAAY;AAC7B,UAAM,MAAM,gBAAgB;AAE5B,QAAI,OAAO,SAAS;AAClB,UAAI,IAAI,EAAE,QAAQ,GAAG,IAAI;AAAA,IAC3B,OAAO;AACL,WAAK;AAAA,IACP;AAAA,EACF;AACF;;;ACjMO,IAAM,sBAAsB,CACjC,aACA,cACA,WACA,YACG;AACH,SAAO,CAAC,YAA4C;AAClD,WAAO,CAAC,KAAK,QAAQ;AACnB,qBAAe,KAAK,KAAK,aAAa,cAAc,UAAU,GAAG,OAAO;AAExE,YAAM,UAAW,IAAY;AAC7B,YAAM,MAAM,gBAAgB;AAE5B,UAAI,OAAO,SAAS;AAClB,eAAO,IAAI,IAAI,EAAE,QAAQ,GAAG,MAAM,QAAQ,KAAK,GAAG,CAAC;AAAA,MACrD;AAEA,aAAO,QAAQ,KAAK,GAAG;AAAA,IACzB;AAAA,EACF;AACF;;;ACrBA,IAAM,kBAAN,MAAsB;AAAA,EACZ,KAAuB;AAAA,EACvB,SAAiC;AAAA,EACjC,YAAoB;AAAA,EAEpB,oBAAoB;AAAA,EACpB,uBAAuB;AAAA,EACvB,iBAAiB;AAAA,EACjB,iBAAuD;AAAA,EAEvD,eAAmC,CAAC;AAAA,EACpC,eAAe;AAAA,EAEf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAwC;AAAA,EAEhD,cAAc;AACZ,SAAK,qBAAqB,IAAI;AAAA,MAC5B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,iBAAiB,IAAI;AAAA,MACxB,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,kBAAkB,IAAI;AAAA,MACzB,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,qBAAqB,IAAI;AAAA,MAC5B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,oBAAoB,IAAI;AAAA,MAC3B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,mBAAmB,IAAI;AAAA,MAC1B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,mBAAmB,IAAI;AAAA,MAC1B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,gBAAgB,IAAI;AAAA,MACvB,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AACA,SAAK,iBAAiB,IAAI;AAAA,MACxB,EAAE,QAAQ,KAAK,kBAAkB;AAAA,MACjC,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,UAAU,QAA0B;AAC1C,UAAM,YAAY,QAAQ,WAAW,cAAc;AAEnD,UAAM,kBAAkB,QAAQ,YAC5B,OAAO,YACP,QAAQ,WAAW,QACjB,uBACA,QAAQ,aACN,GAAG,qBAAqB,GAAG,OAAO,KAClC,GAAG,yBAAyB,GAAG,OAAO;AAE9C,SAAK,SAAS;AAAA,MACZ,GAAG;AAAA,MACH,SAAS,QAAQ,WAAW;AAAA,MAC5B,WAAW;AAAA,MACX,SAAS;AAAA,MACT,wBAAwB,QAAQ,0BAA0B;AAAA,MAC1D,eAAe,QAAQ,iBAAiB;AAAA,MACxC,eAAe,QAAQ,iBAAiB;AAAA,MACxC,uBAAuB,QAAQ,yBAAyB;AAAA,MACxD,sBAAsB,QAAQ,wBAAwB;AAAA,MACtD,uBAAuB,QAAQ,yBAAyB;AAAA,IAC1D;AAEA,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB;AAAA,IACF;AAEA,SAAK,YAAY,gBAAgB;AACjC,SAAK,cAAc,UAAU,KAAK,MAAM;AAExC,QAAI;AACF,UAAI,KAAK,OAAO,wBAAwB;AACtC,aAAK,mBAAmB,MAAM,KAAK,MAAM;AAEzC,YAAI,OAAO,mBAAmB,aAAa;AACzC,eAAK,eAAe,MAAM,KAAK,MAAM;AAAA,QACvC;AAEA,YAAI,SAAS,GAAG;AACd,eAAK,gBAAgB,MAAM,KAAK,MAAM;AAAA,QACxC;AAAA,MACF;AAEA,UAAI,KAAK,OAAO,eAAe;AAC7B,aAAK,mBAAmB,MAAM,KAAK,MAAM;AAEzC,YAAI,SAAS,GAAG;AACd,eAAK,iBAAiB,MAAM,KAAK,MAAM;AAAA,QACzC;AAAA,MACF;AAEA,UAAI,KAAK,OAAO,yBAAyB,CAAC,SAAS,GAAG;AACpD,aAAK,kBAAkB,MAAM,KAAK,MAAM;AAAA,MAC1C;AAEA,UAAI,KAAK,OAAO,UAAU,KAAK,OAAO,sBAAsB;AAC1D,aAAK,iBAAiB,MAAM,KAAK,MAAM;AAAA,MACzC;AAAA,IACF,SAAS,OAAO;AACd,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,MAAM,6CAA6C,KAAK;AAAA,MAClE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,QAA0B;AAChC,SAAK,UAAU,MAAM;AAErB,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB;AAAA,IACF;AAEA,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,GAAwB;AAC5D,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,KAAK,yDAAyD;AAAA,MACxE;AAEA;AAAA,IACF;AAEA,QAAI,KAAK,IAAI;AACX,YAAM,QAAQ,KAAK;AAEnB,YAAM,UAAU;AAChB,YAAM,UAAU;AAChB,YAAM,SAAS;AAGf,UAAI,MAAM,eAAe,GAAG;AAC1B,cAAM,MAAM;AAAA,MACd;AACA,WAAK,KAAK;AAAA,IACZ;AAEA,UAAM,EAAE,WAAW,SAAS,SAAS,IAAI,KAAK;AAE9C,QAAI,CAAC,WAAW;AACd,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,MAAM,iDAAiD;AAAA,MACjE;AACA;AAAA,IACF;AAEA,UAAM,gBACJ,KAAK,OAAO,kBACX,OAAO,cAAc,cAAc,YAAY;AAElD,QAAI,CAAC,eAAe;AAClB,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ;AAAA,UACN;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAEA,QAAI;AACF,WAAK,KAAK,IAAI,cAAc,SAAS;AAErC,YAAM,UAA4B;AAAA,QAChC,OAAO;AAAA,QACP,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK,IAAI;AAAA,QACpB,MAAM;AAAA,UACJ;AAAA,UACA,UACE,aACC,OAAO,IACJ,QACA,OAAO,YAAY,cACjB,SACA;AAAA,UACR,YAAY,KAAK,OAAO,cAAc;AAAA,UACtC,YAAY;AAAA,QACd;AAAA,MACF;AAEA,WAAK,GAAG,SAAS,MAAM;AACrB,aAAK,oBAAoB;AACzB,aAAK,kBAAkB;AACvB,aAAK,YAAY,OAAO;AAAA,MAC1B;AAEA,WAAK,GAAG,YAAY,CAAC,UAAU;AAC7B,YAAI;AACF,gBAAM,UAAU,KAAK,MAAM,MAAM,IAAI;AACrC,eAAK,gBAAgB,OAAO,OAAO;AAAA,QACrC,SAAS,OAAO;AACd,cAAI,KAAK,QAAQ,uBAAuB;AACtC,oBAAQ,MAAM,wCAAwC,KAAK;AAAA,UAC7D;AAAA,QACF;AAAA,MACF;AAEA,WAAK,GAAG,UAAU,CAAC,UAAU;AAC3B,YAAI,KAAK,QAAQ,uBAAuB;AACtC,kBAAQ,MAAM,gCAAgC,KAAK;AAAA,QACrD;AAAA,MACF;AAEA,WAAK,GAAG,UAAU,MAAM;AACtB,aAAK,iBAAiB;AAAA,MACxB;AAAA,IACF,SAAS,OAAO;AACd,UAAI,KAAK,QAAQ,uBAAuB;AACtC,gBAAQ,MAAM,kCAAkC,KAAK;AAAA,MACvD;AACA,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASQ,mBAAmB;AACzB,QAAI,KAAK,qBAAqB,KAAK,sBAAsB;AACvD;AAAA,IACF;AAEA,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAEA,SAAK;AAEL,UAAM,QAAQ,KAAK;AAAA,MACjB,KAAK,iBAAiB,KAAK,IAAI,GAAG,KAAK,oBAAoB,CAAC;AAAA,MAC5D;AAAA,IACF;AAEA,SAAK,iBAAiB,WAAW,MAAM;AACrC,WAAK,iBAAiB;AACtB,WAAK,QAAQ,KAAK,UAAU,MAAS;AAAA,IACvC,GAAG,KAAK;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,oBAAoB;AAC1B,QAAI,KAAK,IAAI,eAAe,EAAwB;AAEpD,WAAO,KAAK,aAAa,SAAS,GAAG;AACnC,YAAM,UAAU,KAAK,aAAa,MAAM;AACxC,UAAI;AAEF,YAAI,WAAW,eAAe,WAAW,CAAC,QAAQ,WAAW;AAC3D,UAAC,QAAgB,YAAY,KAAK;AAAA,QACpC;AACA,aAAK,GAAG,KAAK,cAAc,OAAO,CAAC;AAAA,MACrC,SAAS,OAAO;AACd,YAAI,KAAK,QAAQ,uBAAuB;AACtC,kBAAQ,MAAM,8CAA8C,KAAK;AAAA,QACnE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,YAAY,SAA2B;AAC7C,QAAI,KAAK,IAAI,eAAe,GAAwB;AAClD,WAAK,kBAAkB;AAEvB,UAAI,KAAK,IAAI,eAAe,GAAwB;AAClD,YAAI;AACF,eAAK,GAAG,KAAK,cAAc,OAAO,CAAC;AAAA,QACrC,SAAS,OAAO;AACd,cAAI,KAAK,QAAQ,uBAAuB;AACtC,oBAAQ,MAAM,uCAAuC,KAAK;AAAA,UAC5D;AAEA,eAAK,aAAa,KAAK,OAAO;AAAA,QAChC;AAAA,MACF,OAAO;AACL,aAAK,aAAa,KAAK,OAAO;AAAA,MAChC;AAAA,IACF,OAAO;AACL,UAAI,KAAK,aAAa,UAAU,KAAK,cAAc;AACjD,YAAI,KAAK,QAAQ,uBAAuB;AACtC,kBAAQ;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAEA,aAAK,aAAa,MAAM;AAAA,MAC1B;AAEA,WAAK,aAAa,KAAK,OAAO;AAAA,IAChC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa;AACX,QAAI,KAAK,IAAI;AAEX,WAAK,GAAG,SAAS;AACjB,WAAK,GAAG,UAAU;AAClB,WAAK,GAAG,UAAU;AAElB,UAAI;AAEF,YAAI,KAAK,GAAG,eAAe,KAAK,KAAK,GAAG,eAAe,GAAG;AAExD,cACE,eAAe,KAAK,MACpB,OAAQ,KAAK,GAAW,cAAc,YACtC;AAGA,gBAAK,KAAK,GAAW,SAAS;AAC5B,cAAC,KAAK,GAAW,UAAU;AAAA,YAC7B,OAAO;AAGL,cAAC,KAAK,GAAW,aAAa;AAAA,YAChC;AAAA,UACF,OAAO;AACL,iBAAK,GAAG,MAAM;AAAA,UAChB;AAAA,QACF;AAAA,MACF,SAAS,GAAG;AAAA,MAEZ;AAEA,WAAK,KAAK;AAAA,IACZ;AAEA,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAEA,SAAK,mBAAmB,QAAQ;AAChC,SAAK,eAAe,QAAQ;AAC5B,SAAK,gBAAgB,QAAQ;AAC7B,SAAK,mBAAmB,QAAQ;AAChC,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,kBAAkB,QAAQ;AAC/B,SAAK,iBAAiB,QAAQ;AAC9B,SAAK,cAAc,QAAQ;AAE3B,SAAK,oBAAoB;AACzB,SAAK,eAAe,CAAC;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ;AACN,SAAK,WAAW;AAChB,SAAK,SAAS;AACd,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,QAAqC;AAChD,WAAO,KAAK,cAAc,aAAa,MAAM;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WAAW,WAAmB,UAAsC;AAClE,SAAK,cAAc,WAAW,WAAW,QAAQ;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,YAAY,WAAmB,OAAsB;AACnD,SAAK,cAAc,YAAY,WAAW,KAAK;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAW,SAA6B;AACtC,WAAO;AAAA,MACL,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,cACE,SACA;AACA,UAAM,UAAU;AAAA,MACd,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,IACb;AACA,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF;AAEO,IAAM,YAAY,IAAI,gBAAgB;","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","CommandType","process","self","self","self","self","callback"]}
|