@getlimelight/sdk 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -38,7 +38,7 @@ pnpm add @getlimelight/sdk
38
38
  import { Limelight } from "@getlimelight/sdk";
39
39
 
40
40
  // That's it! One line to start debugging
41
- Limelight.connect();
41
+ Limelight.connect({ projectId: "project-123" });
42
42
  ```
43
43
 
44
44
  ### React Native
@@ -46,7 +46,7 @@ Limelight.connect();
46
46
  ```typescript
47
47
  import { Limelight } from "@getlimelight/sdk";
48
48
 
49
- Limelight.connect();
49
+ Limelight.connect({ projectId: "project-123" });
50
50
  ```
51
51
 
52
52
  ### Expo
@@ -56,6 +56,7 @@ import { Limelight } from "@getlimelight/sdk";
56
56
  import Constants from "expo-constants";
57
57
 
58
58
  Limelight.connect({
59
+ projectId: "project-123",
59
60
  enabled: __DEV__,
60
61
  appName: Constants.expoConfig?.name,
61
62
  });
@@ -69,6 +70,9 @@ Limelight.connect({
69
70
  import { Limelight } from '@getlimelight/sdk';
70
71
 
71
72
  Limelight.connect({
73
+ // The only required field: project Id:
74
+ projectId: string;
75
+
72
76
  // Optional: Platform identifier (auto-detected)
73
77
  platform?: string;
74
78
 
@@ -104,6 +108,7 @@ Limelight.connect({
104
108
  import { Limelight } from "@getlimelight/sdk";
105
109
 
106
110
  Limelight.connect({
111
+ projectId: "project-123",
107
112
  enabled: __DEV__, // Only enable in development
108
113
  appName: "MyAwesomeApp",
109
114
  });
@@ -115,6 +120,7 @@ Limelight.connect({
115
120
  import { Limelight } from "@getlimelight/sdk";
116
121
 
117
122
  Limelight.connect({
123
+ projectId: "project-123",
118
124
  serverUrl: "ws://192.168.1.100:8080", // Your computer's IP
119
125
  appName: "MyApp",
120
126
  });
@@ -220,7 +226,7 @@ Connects to the Limelight server and starts intercepting network requests and co
220
226
  import { Limelight } from "@getlimelight/sdk";
221
227
 
222
228
  // Minimal usage
223
- Limelight.connect();
229
+ Limelight.connect({ projectId: "project-123" });
224
230
 
225
231
  // With configuration
226
232
  Limelight.connect({
@@ -470,13 +476,9 @@ See the `/examples` directory for complete working examples:
470
476
  - Next.js web application
471
477
  - Custom filtering and privacy controls
472
478
 
473
- ## Contributing
474
-
475
- We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
476
-
477
479
  ## License
478
480
 
479
- MIT © [Your Name/Company]
481
+ MIT © LIMELIGHT
480
482
 
481
483
  ## Support
482
484
 
package/dist/index.d.mts CHANGED
@@ -233,6 +233,10 @@ declare enum GraphqlOprtation {
233
233
  * ```
234
234
  */
235
235
  interface LimelightConfig {
236
+ /**
237
+ * The unique project key for authenticating with the Limelight server.
238
+ */
239
+ projectKey: string;
236
240
  /**
237
241
  * The platform of the application (e.g., "ios", "android").
238
242
  */
@@ -277,10 +281,12 @@ interface ConnectionEvent {
277
281
  phase: "CONNECT" | "DISCONNECT";
278
282
  sessionId: string;
279
283
  timestamp: number;
280
- data?: {
284
+ data: {
281
285
  appName?: string;
282
286
  platform?: string;
283
287
  reason?: string;
288
+ projectKey: string;
289
+ sdkVersion: string;
284
290
  };
285
291
  }
286
292
  /**
@@ -340,7 +346,7 @@ declare class LimelightClient {
340
346
  * @param {LimelightConfig} [config] - Optional configuration object.
341
347
  * @returns {void}
342
348
  */
343
- connect(config?: LimelightConfig): void;
349
+ connect(config: LimelightConfig): void;
344
350
  /**
345
351
  * Attempts to reconnect to the Limelight server using exponential backoff.
346
352
  * Will retry up to maxReconnectAttempts times with increasing delays.
package/dist/index.d.ts CHANGED
@@ -233,6 +233,10 @@ declare enum GraphqlOprtation {
233
233
  * ```
234
234
  */
235
235
  interface LimelightConfig {
236
+ /**
237
+ * The unique project key for authenticating with the Limelight server.
238
+ */
239
+ projectKey: string;
236
240
  /**
237
241
  * The platform of the application (e.g., "ios", "android").
238
242
  */
@@ -277,10 +281,12 @@ interface ConnectionEvent {
277
281
  phase: "CONNECT" | "DISCONNECT";
278
282
  sessionId: string;
279
283
  timestamp: number;
280
- data?: {
284
+ data: {
281
285
  appName?: string;
282
286
  platform?: string;
283
287
  reason?: string;
288
+ projectKey: string;
289
+ sdkVersion: string;
284
290
  };
285
291
  }
286
292
  /**
@@ -340,7 +346,7 @@ declare class LimelightClient {
340
346
  * @param {LimelightConfig} [config] - Optional configuration object.
341
347
  * @returns {void}
342
348
  */
343
- connect(config?: LimelightConfig): void;
349
+ connect(config: LimelightConfig): void;
344
350
  /**
345
351
  * Attempts to reconnect to the Limelight server using exponential backoff.
346
352
  * Will retry up to maxReconnectAttempts times with increasing delays.
package/dist/index.js CHANGED
@@ -257,6 +257,7 @@ var SENSITIVE_HEADERS = [
257
257
  ];
258
258
  var DEFAULT_PORT = 9090;
259
259
  var WS_PATH = "/limelight";
260
+ var SDK_VERSION = true ? "0.1.2" : "test-version";
260
261
 
261
262
  // src/helpers/safety/redactSensitiveHeaders.ts
262
263
  var redactSensitiveHeaders = (headers) => {
@@ -1055,7 +1056,9 @@ var LimelightClient = class {
1055
1056
  if (config) {
1056
1057
  this.configure(config);
1057
1058
  } else if (!this.config) {
1058
- this.configure({});
1059
+ throw new Error(
1060
+ "[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field."
1061
+ );
1059
1062
  }
1060
1063
  if (!this.config?.enabled) {
1061
1064
  return;
@@ -1087,7 +1090,9 @@ var LimelightClient = class {
1087
1090
  timestamp: Date.now(),
1088
1091
  data: {
1089
1092
  appName,
1090
- platform: platform || "react-native"
1093
+ platform: platform || (typeof window !== "undefined" ? "web" : "react-native"),
1094
+ projectKey: this.config.projectKey,
1095
+ sdkVersion: SDK_VERSION
1091
1096
  }
1092
1097
  };
1093
1098
  this.ws.onopen = () => {
@@ -1128,7 +1133,13 @@ var LimelightClient = class {
1128
1133
  );
1129
1134
  this.reconnectTimer = setTimeout(() => {
1130
1135
  this.reconnectTimer = null;
1131
- this.connect();
1136
+ if (this.config) {
1137
+ this.configure(this.config);
1138
+ } else if (!this.config) {
1139
+ throw new Error(
1140
+ "[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field."
1141
+ );
1142
+ }
1132
1143
  }, delay);
1133
1144
  }
1134
1145
  /**
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["export { Limelight } from \"./limelight\";\nexport type { LimelightConfig } from \"./types\";\nexport * from \"./types\";\n","import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n const responseBody = serializeBody(\n this.responseText || this.response,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, and console interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config?: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n this.configure({});\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform: platform || \"react-native\",\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACKO,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;AAHA,SAAAA;AAAA,GAAA;AAML,IAAK,eAAL,kBAAKC,kBAAL;AACL,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,cAAW;AACX,EAAAA,cAAA,WAAQ;AAJE,SAAAA;AAAA,GAAA;AAOL,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;AA4GL,IAAK,YAAL,kBAAKC,eAAL;AACL,EAAAA,WAAA,aAAU;AACV,EAAAA,WAAA,aAAU;AAFA,SAAAA;AAAA,GAAA;;;ACrIL,IAAK,mBAAL,kBAAKC,sBAAL;AACL,EAAAA,kBAAA,WAAQ;AACR,EAAAA,kBAAA,cAAW;AACX,EAAAA,kBAAA,SAAM;AAHI,SAAAA;AAAA,GAAA;;;ACbL,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;;;ACnBO,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;;;ACjCO,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;AAUO,IAAM,eAAe;AAKrB,IAAM,UAAU;;;AC9BhB,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,QAAsB;AAEvC,QAAMC,WAAU,CAAC,KAAc,iBAA8B;AAC3D,QAAI,QAAQ,KAAM,QAAO;AACzB,QAAI,QAAQ,OAAW,QAAO;AAC9B,QAAI,OAAO,QAAQ,SAAU,QAAO,GAAG,GAAG;AAC1C,QAAI,OAAO,QAAQ,SAAU,QAAO,IAAI,SAAS;AACjD,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,QAAI,KAAK,IAAI,GAAG,GAAG;AACjB,aAAO;AAAA,IACT;AACA,SAAK,IAAI,KAAK,IAAI;AAElB,QAAI,eAAe,OAAO;AACxB,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,MAAM,IAAI;AAAA,QACV,SAAS,IAAI;AAAA,QACb,OAAO,IAAI;AAAA,MACb;AAAA,IACF;AAEA,QAAI,eAAe,MAAM;AACvB,aAAO,IAAI,YAAY;AAAA,IACzB;AAEA,QAAI,eAAe,QAAQ;AACzB,aAAO,IAAI,SAAS;AAAA,IACtB;AAEA,QAAI,eAAe,KAAK;AACtB,YAAM,MAA2B,CAAC;AAClC,UAAI,QAAQ,CAAC,GAAG,MAAM;AACpB,cAAM,MAAM,OAAO,MAAM,WAAW,IAAI,OAAO,CAAC;AAChD,YAAI,GAAG,IAAIA,SAAQ,GAAG,eAAe,CAAC;AAAA,MACxC,CAAC;AACD,aAAO;AAAA,IACT;AAEA,QAAI,eAAe,KAAK;AACtB,aAAO,MAAM,KAAK,GAAG,EAAE,IAAI,CAAC,MAAMA,SAAQ,GAAG,eAAe,CAAC,CAAC;AAAA,IAChE;AAEA,QAAI,YAAY,OAAO,GAAG,GAAG;AAC3B,aAAO,IAAI,IAAI,YAAY,IAAI,IAAK,IAAY,MAAM;AAAA,IACxD;AAEA,QAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,aAAO,IAAI,IAAI,CAAC,SAASA,SAAQ,MAAM,eAAe,CAAC,CAAC;AAAA,IAC1D;AAEA,UAAM,SAA8B,CAAC;AACrC,eAAW,OAAO,KAAK;AACrB,UAAI,OAAO,UAAU,eAAe,KAAK,KAAK,GAAG,GAAG;AAClD,eAAO,GAAG,IAAIA,SAAS,IAAY,GAAG,GAAG,eAAe,CAAC;AAAA,MAC3D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,YAAYA,SAAQ,OAAO,CAAC;AAClC,WAAO,KAAK,UAAU,WAAW,MAAM,SAAS,IAAI,CAAC;AAAA,EACvD,SAAS,OAAO;AACd,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS;AAAA,MACT,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,IAChE,CAAC;AAAA,EACH;AACF;;;ACjFO,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;;;ACPO,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,cAAQ,KAAK,gDAAgD;AAC7D;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAM,OAAO;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,YAAI,KAAK,eAAe;AACtB,iBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,QACrC;AAEA,aAAK,gBAAgB;AAErB,YAAI;AACF,gBAAM,SAAS,gBAAgB;AAC/B,gBAAM,cAAc,kBAAkB,OAAO,IAAI;AACjD,gBAAM,aAAa,KAAK,kBAAkB;AAE1C,cAAI,eAA6B;AAAA,YAC/B,IAAI,GAAG,KAAK,aAAa,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,SAAS;AAAA,YAC1D,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA,WAAW,KAAK,IAAI;AAAA,YACpB,WAAW,KAAK,aAAa;AAAA,YAC7B;AAAA,YACA;AAAA,YACA,MAAM,KAAK,IAAI,CAAC,QAAQ,cAAc,GAAG,CAAC;AAAA,YAC1C;AAAA,UACF;AAEA,cAAI,KAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgB,KAAK,OAAO,WAAW,YAAY;AAEzD,gBAAI,CAAC,eAAe;AAClB,qBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,YACrC;AAEA,gBAAI,cAAc,UAAU,WAAW;AACrC,sBAAQ;AAAA,gBACN;AAAA,cACF;AACA,qBAAO,SAAS,MAAM,SAAS,IAAI;AAAA,YACrC;AAEA,2BAAe;AAAA,UACjB;AAEA,eAAK,YAAY,YAAY;AAAA,QAC/B,SAAS,OAAO;AAAA,QAEhB,UAAE;AACA,eAAK,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,cAAQ,KAAK,4CAA4C;AACzD;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;;;AChJO,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;;;ACGO,IAAM,qBAAN,MAAyB;AAAA,EAK9B,YACU,aACA,cACR;AAFQ;AACA;AAER,SAAK,gBAAgB,OAAO;AAAA,EAC9B;AAAA,EATQ;AAAA,EACA,SAAiC;AAAA,EACjC,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBlB,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,cAAQ,KAAK,gDAAgD;AAC7D;AAAA,IACF;AACA,SAAK,UAAU;AAEf,SAAK,SAAS;AACd,UAAM,OAAO;AAEb,WAAO,QAAQ,eACb,OACA,OAAoB,CAAC,GACF;AACnB,YAAM,YAAY,kBAAkB;AACpC,YAAM,YAAY,KAAK,IAAI;AAE3B,YAAM,MACJ,OAAO,UAAU,WACb,QACA,iBAAiB,MACjB,MAAM,SAAS,IACf,MAAM;AAEZ,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,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;AACzB,kBAAQ;AAAA,YACN;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,cAAc;AAAA,QAClB;AAAA,QACA,KAAK,QAAQ;AAAA,MACf;AAEA,UAAI,cAAyC;AAE7C,UAAI,KAAK,QAAQ,iBAAiB,iBAAiB,KAAK,WAAW,GAAG;AAEpE,cAAM,UAAU,aAAa;AAC7B,YAAI,SAAS;AACX,wBAAc,aAAa,OAAO,KAAK;AAAA,QACzC;AAAA,MACF;AAEA,UAAI,eAAiC;AAAA,QACnC,IAAI;AAAA,QACJ,WAAW,KAAK,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,UAAI,KAAK,QAAQ,YAAY;AAC3B,cAAM,gBAAgB,KAAK,OAAO,WAAW,YAAY;AAEzD,YAAI,CAAC,eAAe;AAClB,iBAAO,KAAK,cAAc,OAAO,YAAY;AAAA,QAC/C;AAEA,YAAI,cAAc,mCAAgC;AAChD,kBAAQ,MAAM,oDAAoD;AAClE,iBAAO,KAAK,cAAc,OAAO,YAAY;AAAA,QAC/C;AAEA,uBAAe;AAAA,MACjB;AAEA,WAAK,YAAY,YAAY;AAE7B,UAAI;AACF,cAAM,WAAW,MAAM,KAAK,cAAc,OAAO,YAAY;AAC7D,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,UACA,KAAK,QAAQ;AAAA,QACf;AAEA,YAAI,gBAAkC;AAAA,UACpC,IAAI;AAAA,UACJ,WAAW,KAAK,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,YAAI,KAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgB,KAAK,OAAO,WAAW,aAAa;AAE1D,cAAI,CAAC,eAAe;AAClB,mBAAO;AAAA,UACT;AAEA,cAAI,cAAc,qCAAiC;AACjD,oBAAQ,MAAM,oDAAoD;AAClE,mBAAO;AAAA,UACT;AAEA,0BAAgB;AAAA,QAClB;AAEA,aAAK,YAAY,aAAa;AAC9B,eAAO;AAAA,MACT,SAAS,KAAK;AACZ,cAAM,eAAe,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AACpE,cAAM,aAAa,eAAe,QAAQ,IAAI,QAAQ;AAEtD,YAAI,aAAgC;AAAA,UAClC,IAAI;AAAA,UACJ,WAAW,KAAK,aAAa;AAAA,UAC7B,WAAW,KAAK,IAAI;AAAA,UACpB;AAAA,UACA;AAAA,UACA;AAAA,UACA,OAAO;AAAA,QACT;AAEA,YAAI,KAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgB,KAAK,OAAO,WAAW,UAAU;AAEvD,cAAI,iBAAiB,cAAc,+BAA8B;AAC/D,yBAAa;AAAA,UACf;AAAA,QACF;AAEA,aAAK,YAAY,UAAU;AAE3B,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,UAAU;AACR,QAAI,CAAC,KAAK,SAAS;AACjB,cAAQ,KAAK,4CAA4C;AACzD;AAAA,IACF;AACA,SAAK,UAAU;AAEf,WAAO,QAAQ,KAAK;AAAA,EACtB;AACF;;;AC5NO,IAAM,iBAAN,MAAqB;AAAA,EAQ1B,YACU,aACA,cACR;AAFQ;AACA;AAER,SAAK,kBAAkB,eAAe,UAAU;AAChD,SAAK,kBAAkB,eAAe,UAAU;AAChD,SAAK,8BACH,eAAe,UAAU;AAAA,EAC7B;AAAA,EAfQ;AAAA,EACA;AAAA,EACA;AAAA,EAEA,UAAU;AAAA,EACV,SAAiC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBzC,MAAM,QAAyB;AAC7B,QAAI,KAAK,SAAS;AAChB,cAAQ,KAAK,4CAA4C;AACzD;AAAA,IACF;AACA,SAAK,UAAU;AACf,SAAK,SAAS;AAEd,UAAM,OAAO;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,aAAO,KAAK,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,aAAO,KAAK,4BAA4B,MAAM,MAAM,SAAgB;AAAA,IACtE;AAEA,mBAAe,UAAU,OAAO,SAAU,MAAM;AAC9C,YAAM,OAAO,KAAK;AAElB,UAAI,MAAM,eAAe;AACvB,eAAO,KAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,MAC1D;AAEA,UAAI,MAAM;AACR,cAAM,cAAc;AAAA,UAClB;AAAA,UACA,KAAK,QAAQ;AAAA,QACf;AAEA,YAAI,eAAiC;AAAA,UACnC,IAAI,KAAK;AAAA,UACT,WAAW,KAAK,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,YAAI,KAAK,QAAQ,YAAY;AAC3B,gBAAM,gBAAgB,KAAK,OAAO,WAAW,YAAY;AAEzD,cAAI,CAAC,eAAe;AAClB,mBAAO,KAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,UAC1D;AAEA,cAAI,cAAc,mCAAgC;AAChD,oBAAQ,MAAM,oDAAoD;AAClE,mBAAO,KAAK,gBAAgB,MAAM,MAAM,SAAgB;AAAA,UAC1D;AAEA,yBAAe;AAAA,QACjB;AAEA,aAAK,YAAY,YAAY;AAE7B,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;AAClB,yBAAe;AAEf,gBAAM,UAAU,KAAK,IAAI;AACzB,gBAAM,WAAW,UAAU,KAAK;AAChC,gBAAM,kBAAkB,KAAK;AAAA,YAC3B,KAAK,sBAAsB;AAAA,UAC7B;AAEA,gBAAM,eAAe;AAAA,YACnB,KAAK,gBAAgB,KAAK;AAAA,YAC1B,KAAK,QAAQ;AAAA,UACf;AAEA,cAAI,gBAAkC;AAAA,YACpC,IAAI,KAAK;AAAA,YACT,WAAW,KAAK,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,cAAI,KAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgB,KAAK,OAAO,WAAW,aAAa;AAE1D,gBAAI,CAAC,eAAe;AAClB;AAAA,YACF;AAEA,gBAAI,cAAc,qCAAiC;AACjD,sBAAQ;AAAA,gBACN;AAAA,cACF;AACA;AAAA,YACF;AAEA,4BAAgB;AAAA,UAClB;AAEA,eAAK,YAAY,aAAa;AAC9B,kBAAQ,KAAK,IAAI;AAAA,QACnB;AAMA,cAAM,YAAY,CAAC,iBAAyB;AAC1C,cAAI,aAAc;AAClB,yBAAe;AAEf,cAAI,aAAgC;AAAA,YAClC,IAAI,KAAK;AAAA,YACT,WAAW,KAAK,aAAa;AAAA,YAC7B,WAAW,KAAK,IAAI;AAAA,YACpB;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAEA,cAAI,KAAK,QAAQ,YAAY;AAC3B,kBAAM,gBAAgB,KAAK,OAAO,WAAW,UAAU;AAEvD,gBAAI,iBAAiB,cAAc,+BAA8B;AAC/D,2BAAa;AAAA,YACf;AAAA,UACF;AAEA,eAAK,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,iBAAiB;AAC3B,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,aAAO,KAAK,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,cAAQ,KAAK,wCAAwC;AACrD;AAAA,IACF;AACA,SAAK,UAAU;AAEf,mBAAe,UAAU,OAAO,KAAK;AACrC,mBAAe,UAAU,OAAO,KAAK;AACrC,mBAAe,UAAU,mBACvB,KAAK;AAAA,EACT;AACF;;;ACrUA,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,EAER,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,qBAAqB,IAAI;AAAA,MAC5B,KAAK,YAAY,KAAK,IAAI;AAAA,MAC1B,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,UAAU,QAAyB;AACzC,UAAM,YAAY,OAAO,WAAW,cAAc;AAElD,SAAK,SAAS;AAAA,MACZ,SAAS;AAAA,MACT,WAAW,kBAAkB,YAAY,GAAG,OAAO;AAAA,MACnD,SAAS;AAAA,MACT,wBAAwB;AAAA,MACxB,eAAe;AAAA,MACf,eAAe;AAAA,MACf,GAAG;AAAA,IACL;AAEA,QAAI,CAAC,KAAK,OAAO,SAAS;AACxB;AAAA,IACF;AAEA,SAAK,YAAY,gBAAgB;AAEjC,QAAI;AACF,UAAI,KAAK,OAAO,wBAAwB;AACtC,aAAK,mBAAmB,MAAM,KAAK,MAAM;AACzC,aAAK,eAAe,MAAM,KAAK,MAAM;AAAA,MACvC;AAEA,UAAI,KAAK,OAAO,eAAe;AAC7B,aAAK,mBAAmB,MAAM,KAAK,MAAM;AAAA,MAC3C;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,6CAA6C,KAAK;AAAA,IAClE;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,QAA0B;AAChC,QAAI,QAAQ;AACV,WAAK,UAAU,MAAM;AAAA,IACvB,WAAW,CAAC,KAAK,QAAQ;AACvB,WAAK,UAAU,CAAC,CAAC;AAAA,IACnB;AAEA,QAAI,CAAC,KAAK,QAAQ,SAAS;AACzB;AAAA,IACF;AAEA,QAAI,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AACpD,cAAQ,KAAK,yDAAyD;AACtE;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;AAEA,WAAK,KAAK;AAAA,IACZ;AACA,UAAM,EAAE,WAAW,SAAS,SAAS,IAAI,KAAK;AAE9C,QAAI,CAAC,WAAW;AACd,cAAQ,MAAM,iDAAiD;AAC/D;AAAA,IACF;AAEA,QAAI;AACF,WAAK,KAAK,IAAI,UAAU,SAAS;AAEjC,YAAM,UAA4B;AAAA,QAChC,OAAO;AAAA,QACP,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK,IAAI;AAAA,QACpB,MAAM;AAAA,UACJ;AAAA,UACA,UAAU,YAAY;AAAA,QACxB;AAAA,MACF;AAEA,WAAK,GAAG,SAAS,MAAM;AACrB,aAAK,oBAAoB;AACzB,aAAK,kBAAkB;AACvB,aAAK,YAAY,OAAO;AAAA,MAC1B;AAEA,WAAK,GAAG,UAAU,CAAC,UAAU;AAC3B,gBAAQ,MAAM,gCAAgC,KAAK;AAAA,MACrD;AAEA,WAAK,GAAG,UAAU,MAAM;AACtB,aAAK,iBAAiB;AAAA,MACxB;AAAA,IACF,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AACrD,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;AACL,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;AAAA,IACf,GAAG,KAAK;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,oBAAoB;AAC1B,QAAI,KAAK,IAAI,eAAe,UAAU,KAAM;AAE5C,WAAO,KAAK,aAAa,SAAS,GAAG;AACnC,YAAM,UAAU,KAAK,aAAa,MAAM;AACxC,UAAI;AACF,aAAK,GAAG,KAAK,cAAc,OAAO,CAAC;AAAA,MACrC,SAAS,OAAO;AACd,gBAAQ,MAAM,8CAA8C,KAAK;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,YAAY,SAA2B;AAC7C,QAAI,KAAK,IAAI,eAAe,UAAU,MAAM;AAC1C,WAAK,kBAAkB;AAEvB,UAAI,KAAK,IAAI,eAAe,UAAU,MAAM;AAC1C,YAAI;AACF,eAAK,GAAG,KAAK,cAAc,OAAO,CAAC;AAAA,QACrC,SAAS,OAAO;AACd,kBAAQ,MAAM,uCAAuC,KAAK;AAC1D,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,gBAAQ,KAAK,yDAAyD;AACtE,aAAK,aAAa,MAAM;AAAA,MAC1B;AACA,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;AAGA,QAAI,KAAK,gBAAgB;AACvB,mBAAa,KAAK,cAAc;AAChC,WAAK,iBAAiB;AAAA,IACxB;AAEA,SAAK,mBAAmB,QAAQ;AAChC,SAAK,eAAe,QAAQ;AAC5B,SAAK,mBAAmB,QAAQ;AAEhC,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;AACF;AAEO,IAAM,YAAY,IAAI,gBAAgB;","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["export { Limelight } from \"./limelight\";\nexport type { LimelightConfig } from \"./types\";\nexport * from \"./types\";\n","import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n const responseBody = serializeBody(\n this.responseText || this.response,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, SDK_VERSION, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, and console interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
package/dist/index.mjs CHANGED
@@ -221,6 +221,7 @@ var SENSITIVE_HEADERS = [
221
221
  ];
222
222
  var DEFAULT_PORT = 9090;
223
223
  var WS_PATH = "/limelight";
224
+ var SDK_VERSION = true ? "0.1.2" : "test-version";
224
225
 
225
226
  // src/helpers/safety/redactSensitiveHeaders.ts
226
227
  var redactSensitiveHeaders = (headers) => {
@@ -1019,7 +1020,9 @@ var LimelightClient = class {
1019
1020
  if (config) {
1020
1021
  this.configure(config);
1021
1022
  } else if (!this.config) {
1022
- this.configure({});
1023
+ throw new Error(
1024
+ "[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field."
1025
+ );
1023
1026
  }
1024
1027
  if (!this.config?.enabled) {
1025
1028
  return;
@@ -1051,7 +1054,9 @@ var LimelightClient = class {
1051
1054
  timestamp: Date.now(),
1052
1055
  data: {
1053
1056
  appName,
1054
- platform: platform || "react-native"
1057
+ platform: platform || (typeof window !== "undefined" ? "web" : "react-native"),
1058
+ projectKey: this.config.projectKey,
1059
+ sdkVersion: SDK_VERSION
1055
1060
  }
1056
1061
  };
1057
1062
  this.ws.onopen = () => {
@@ -1092,7 +1097,13 @@ var LimelightClient = class {
1092
1097
  );
1093
1098
  this.reconnectTimer = setTimeout(() => {
1094
1099
  this.reconnectTimer = null;
1095
- this.connect();
1100
+ if (this.config) {
1101
+ this.configure(this.config);
1102
+ } else if (!this.config) {
1103
+ throw new Error(
1104
+ "[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field."
1105
+ );
1106
+ }
1096
1107
  }, delay);
1097
1108
  }
1098
1109
  /**
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n const responseBody = serializeBody(\n this.responseText || this.response,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, and console interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config?: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n this.configure({});\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform: platform || \"react-native\",\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
1
+ {"version":3,"sources":["../src/types/console.ts","../src/types/core.ts","../src/types/graphql.ts","../src/helpers/detection/detectConsoleType.ts","../src/helpers/detection/detectSource.ts","../src/helpers/detection/getInitiator.ts","../src/helpers/graphql/detectGraphQlOperationType.ts","../src/helpers/graphql/isGraphQLRequest.ts","../src/helpers/graphql/parseGraphQL.ts","../src/constants/index.ts","../src/helpers/safety/redactSensitiveHeaders.ts","../src/helpers/safety/safeStringify.ts","../src/helpers/utils/serializeBody.ts","../src/helpers/utils/isDevelopment.ts","../src/helpers/utils/formatRequestName.ts","../src/limelight/interceptors/ConsoleInterceptor.ts","../src/protocol/protocol.ts","../src/limelight/interceptors/NetworkInterceptor.ts","../src/limelight/interceptors/XHRInterceptor.ts","../src/limelight/LimelightClient.ts"],"sourcesContent":["import { EventType } from \"./core\";\n\n/**\n * Console log levels\n */\nexport enum ConsoleLevel {\n LOG = \"log\",\n WARN = \"warn\",\n ERROR = \"error\",\n INFO = \"info\",\n DEBUG = \"debug\",\n TRACE = \"trace\",\n}\n\n/**\n * Where logs originate from\n */\nexport enum ConsoleSource {\n APP = \"app\",\n LIBRARY = \"library\",\n REACT_NATIVE = \"react-native\",\n NATIVE = \"native\",\n}\n\n/**\n * Type of console log\n */\nexport enum ConsoleType {\n EXCEPTION = \"exception\",\n WARNING = \"warning\",\n NETWORK = \"network\",\n PERFORMANCE = \"performance\",\n GENERAL = \"general\",\n}\n\n/**\n * Console log event from the app\n */\nexport interface ConsoleEvent {\n id: string;\n phase: \"CONSOLE\";\n type: EventType.CONSOLE;\n level: ConsoleLevel;\n timestamp: number;\n sessionId: string;\n source: ConsoleSource;\n consoleType: ConsoleType;\n args: string[];\n stackTrace?: string;\n}\n","import {\n GraphqlOprtation,\n GraphQLRequest,\n GraphQLResponse,\n ConsoleEvent,\n} from \"./index\";\n\n// ============================================================================\n// ENUMS\n// ============================================================================\n\nexport enum NetworkType {\n FETCH = \"fetch\",\n XHR = \"xhr\",\n GRAPHQL = \"graphql\",\n}\n\nexport enum NetworkPhase {\n CONNECT = \"CONNECT\",\n REQUEST = \"REQUEST\",\n RESPONSE = \"RESPONSE\",\n ERROR = \"ERROR\",\n}\n\nexport enum BodyFormat {\n TEXT = \"TEXT\",\n JSON = \"JSON\",\n FORM_DATA = \"FORM_DATA\",\n BLOB = \"BLOB\",\n ARRAY_BUFFER = \"ARRAY_BUFFER\",\n NONE = \"NONE\",\n UNSERIALIZABLE = \"UNSERIALIZABLE\",\n}\n\nexport enum HttpMethod {\n GET = \"GET\",\n POST = \"POST\",\n PUT = \"PUT\",\n PATCH = \"PATCH\",\n DELETE = \"DELETE\",\n HEAD = \"HEAD\",\n OPTIONS = \"OPTIONS\",\n TRACE = \"TRACE\",\n CONNECT = \"CONNECT\",\n}\n\nexport enum HttpStatusClass {\n INFORMATIONAL = 100,\n SUCCESS = 200,\n REDIRECTION = 300,\n CLIENT_ERROR = 400,\n SERVER_ERROR = 500,\n}\n\n// ============================================================================\n// BODY SERIALIZATION\n// ============================================================================\n\n/**\n * Normalized serialized body format\n */\nexport interface SerializedBody {\n format: BodyFormat;\n size: number; // bytes (approx)\n preview: string; // truncated view (\"{...}\", \"[FormData]\", \"[Blob]\")\n raw?: string; // optional full string version when feasible\n}\n\n// ============================================================================\n// NETWORK EVENTS (sent by SDK)\n// ============================================================================\n\n/**\n * Base shape all network events share\n */\nexport interface BaseNetworkEvent {\n id: string; // request ID linking request/response/error\n sessionId: string;\n timestamp: number; // unix ms\n phase: NetworkPhase;\n networkType: NetworkType;\n graphql?: {\n operationName?: string;\n operationType?: GraphqlOprtation | null;\n variables?: any;\n query?: string;\n };\n}\n\n/**\n * The REQUEST event your RN client sends first\n */\nexport interface NetworkRequest extends BaseNetworkEvent {\n phase: NetworkPhase.REQUEST;\n url: string;\n method: HttpMethod;\n headers: Record<string, string>;\n body?: SerializedBody;\n name: string; // short friendly name (\"/posts\", \"countries\")\n initiator: string; // \"fetch()\", \"graphql()\", \"axios\", etc\n requestSize: number; // estimated byte size of outbound payload\n}\n\n/**\n * The RESPONSE event (2nd step)\n */\nexport interface NetworkResponse extends BaseNetworkEvent {\n phase: NetworkPhase.RESPONSE;\n status: number;\n statusText: string;\n headers: Record<string, string>;\n body?: SerializedBody;\n duration: number; // ms\n responseSize: number; // bytes\n redirected: boolean;\n ok: boolean;\n}\n\n/**\n * NETWORK ERROR (3rd possible outcome)\n */\nexport interface NetworkErrorEvent extends BaseNetworkEvent {\n phase: NetworkPhase.ERROR;\n errorMessage: string;\n stack?: string;\n}\n\n/**\n * CONNECT event (session start)\n */\nexport interface ConnectEvent {\n phase: NetworkPhase.CONNECT;\n sessionId: string;\n timestamp: number;\n data: {\n appName: string;\n platform: \"ios\" | \"android\";\n };\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n error?: NetworkErrorEvent;\n}\n\nexport enum EventType {\n NETWORK = \"NETWORK\",\n CONSOLE = \"CONSOLE\",\n}\n\n// ============================================================================\n// UNION TYPES\n// ============================================================================\n/**\n * All possible events that can be sent over WebSocket\n */\nexport type NetworkEvent =\n | ConnectEvent\n | NetworkRequest\n | NetworkResponse\n | NetworkErrorEvent\n | GraphQLRequest\n | GraphQLResponse;\n\nexport type LimelightEvent = NetworkEvent | ConsoleEvent;\n\n// ============================================================================\n// SESSION\n// ============================================================================\nexport interface Session {\n id: string;\n appName: string;\n platform: \"ios\" | \"android\";\n connectedAt: number;\n}\n\n// ============================================================================\n// WEB UI HELPER TYPES\n// ============================================================================\n/**\n * Request with its corresponding response (for UI display)\n */\nexport interface NetworkRequestWithResponse extends NetworkRequest {\n response?: NetworkResponse;\n status?: number;\n duration?: number;\n}\n","import { NetworkRequest, NetworkResponse, NetworkType } from \"./index\";\n\n/**\n * GRAPHQL EXTENSIONS\n */\nexport interface GraphQLRequest extends NetworkRequest {\n networkType: NetworkType.GRAPHQL;\n query: string;\n variables?: Record<string, any>;\n operationName?: string;\n}\n\n/**\n * GRAPHQL Response\n */\nexport interface GraphQLResponse extends NetworkResponse {\n networkType: NetworkType.GRAPHQL;\n data?: any;\n errors?: any[];\n}\n\nexport enum GraphqlOprtation {\n QUERY = \"QUERY\",\n MUTATION = \"MUTATION\",\n SUB = \"SUBSCRIPTION\",\n}\n","import { ConsoleType } from \"@/types\";\n\n/**\n * Detects the type of console message based on its level and content.\n * @param level - The console log level (e.g., \"log\", \"warn\", \"error\", \"info\", \"debug\").\n * @param args - The arguments passed to the console method.\n * @returns The detected ConsoleType.\n */\nexport const detectConsoleType = (\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\" | \"trace\",\n args: any[]\n): ConsoleType => {\n const messageStr = args\n .map((arg) => {\n try {\n return typeof arg === \"object\" ? JSON.stringify(arg) : String(arg);\n } catch {\n return String(arg);\n }\n })\n .join(\" \")\n .toLowerCase();\n\n if (level === \"error\") {\n if (\n messageStr.includes(\"error:\") ||\n messageStr.includes(\"exception\") ||\n messageStr.includes(\"uncaught\") ||\n messageStr.includes(\"unhandled\") ||\n args.some((arg) => arg instanceof Error)\n ) {\n return ConsoleType.EXCEPTION;\n }\n }\n\n if (level === \"warn\") {\n return ConsoleType.WARNING;\n }\n\n if (\n messageStr.includes(\"network\") ||\n messageStr.includes(\"fetch\") ||\n messageStr.includes(\"request\") ||\n messageStr.includes(\"response\") ||\n messageStr.includes(\"http\") ||\n messageStr.includes(\"api\") ||\n messageStr.includes(\"graphql\") ||\n messageStr.includes(\"xhr\")\n ) {\n return ConsoleType.NETWORK;\n }\n\n if (\n messageStr.includes(\"performance\") ||\n messageStr.includes(\"slow\") ||\n messageStr.includes(\"render\") ||\n messageStr.includes(\"fps\") ||\n messageStr.includes(\"memory\") ||\n messageStr.includes(\"optimization\") ||\n messageStr.includes(\"bottleneck\")\n ) {\n return ConsoleType.PERFORMANCE;\n }\n\n return ConsoleType.GENERAL;\n};\n","import { ConsoleSource } from \"@/types\";\n/**\n * Detects the source of a console log by analyzing the stack trace.\n * @return {ConsoleSource} The detected source of the console log.\n */\nexport const detectLogSource = (): ConsoleSource => {\n try {\n const stack = new Error().stack;\n\n if (!stack) return ConsoleSource.APP;\n\n const stackLines = stack.split(\"\\n\");\n\n for (let i = 3; i < stackLines.length; i++) {\n const line = stackLines[i];\n\n if (line === undefined) return ConsoleSource.APP;\n\n if (\n line.includes(\"node_modules/react-native/\") ||\n line.includes(\"react-native/Libraries/\") ||\n line.includes(\"MessageQueue.js\") ||\n line.includes(\"BatchedBridge\")\n ) {\n return ConsoleSource.REACT_NATIVE;\n }\n\n if (line.includes(\"[native code]\") || line.includes(\"NativeModules\")) {\n return ConsoleSource.NATIVE;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n\n if (!line.includes(\"node_modules/\")) {\n return ConsoleSource.APP;\n }\n }\n\n return ConsoleSource.APP;\n } catch {\n return ConsoleSource.APP;\n }\n};\n","/**\n * Gets the function name and file location of the caller that initiated the current function.\n * @returns A string representing the initiator function and its file location.\n */\nexport const getInitiator = (): string => {\n try {\n const stack = new Error().stack;\n if (!stack) return \"unknown\";\n\n const lines = stack.split(\"\\n\");\n const callerLine = lines[4] || lines[3];\n\n if (!callerLine) return \"unknown\";\n\n const match = callerLine.match(/at (.+) \\((.+):(\\d+):(\\d+)\\)/);\n if (match) {\n const [, functionName, filePath, line] = match;\n const fileName = filePath?.split(\"/\").pop();\n\n return `${functionName} (${fileName}:${line})`;\n }\n\n return callerLine.trim();\n } catch {\n return \"unknown\";\n }\n};\n","import { GraphqlOprtation } from \"@/types\";\n\n/**\n * Detects the GraphQL operation type from a query string.\n * @param query - The GraphQL query string.\n * @returns The detected GraphQL operation type or null if not detectable.\n */\nexport const detectGraphQlOperationType = (\n query?: string\n): GraphqlOprtation | null => {\n if (!query) return null;\n if (query.trim().startsWith(\"mutation\")) return GraphqlOprtation.MUTATION;\n if (query.trim().startsWith(\"subscription\")) return GraphqlOprtation.SUB;\n\n return GraphqlOprtation.QUERY;\n};\n","/**\n * Determines if a given request is a GraphQL request based on the URL and body content.\n */\nexport const isGraphQLRequest = (url: string, body: any): boolean => {\n const isGraphqlUrl = url.toLowerCase().includes(\"graphql\");\n\n const rawBody = typeof body === \"object\" && body !== null ? body.raw : body;\n\n if (typeof rawBody !== \"string\") return isGraphqlUrl;\n\n try {\n if (rawBody.includes('\"query\"') || rawBody.includes('\"operationName\"')) {\n return true;\n }\n } catch {}\n\n return isGraphqlUrl;\n};\n","import { NetworkRequest } from \"@/types\";\nimport { detectGraphQlOperationType } from \"./detectGraphQlOperationType\";\n\n/**\n * WARNING: Do NOT include raw variables or query literals in production payloads.\n * Variables and literals may contain sensitive user information.\n * Only operationName and operationType are safe to send at launch.\n *\n * Parses a GraphQL request body and extracts relevant information.\n * @param body - The request body to parse.\n * @returns An object containing GraphQL operation details or null if parsing fails.\n */\nexport const parseGraphQL = (body: any): NetworkRequest[\"graphql\"] | null => {\n try {\n // 1. Get the JSON object regardless of what's passed\n const parsed = typeof body === \"string\" ? JSON.parse(body) : body;\n\n // 2. Defensive check: ensure 'parsed' is an object and not null\n if (!parsed || typeof parsed !== \"object\") {\n return null;\n }\n\n // 3. Only return if there is at least a query (standard GraphQL)\n if (!parsed.query && !parsed.operationName) {\n return null;\n }\n\n return {\n operationName: parsed.operationName || undefined,\n operationType: detectGraphQlOperationType(parsed.query),\n variables: parsed.variables || undefined,\n query: parsed.query || undefined,\n };\n } catch {\n return null;\n }\n};\n","/**\n * Constants used throughout the Limelight application.\n */\nexport const SENSITIVE_HEADERS = [\n \"authorization\",\n \"cookie\",\n \"set-cookie\",\n \"x-api-key\",\n \"x-auth-token\",\n \"x-access-token\",\n \"api-key\",\n \"apikey\",\n \"proxy-authorization\",\n \"x-csrf-token\",\n \"x-xsrf-token\",\n \"x-auth\",\n \"auth-token\",\n \"access-token\",\n \"secret\",\n \"x-secret\",\n \"bearer\",\n];\n\n/**\n * The current protocol version used by Limelight.\n */\nexport const PROTOCOL_VERSION = \"0.1.0\";\n\n/**\n * Default port number for the Limelight WebSocket server.\n */\nexport const DEFAULT_PORT = 9090;\n\n/**\n * The WebSocket path for Limelight connections.\n */\nexport const WS_PATH = \"/limelight\";\n\n/**\n * The current SDK version of Limelight.\n */\ndeclare const __SDK_VERSION__: string;\nexport const SDK_VERSION =\n typeof __SDK_VERSION__ !== \"undefined\" ? __SDK_VERSION__ : \"test-version\";\n","import { SENSITIVE_HEADERS } from \"@/constants\";\n\n/**\n * Redacts sensitive headers from a given headers object.\n * @param {Record<string, string>} headers - The headers object to redact.\n */\nexport const redactSensitiveHeaders = (\n headers: Record<string, string>\n): Record<string, string> => {\n const redacted = { ...headers };\n\n Object.keys(redacted).forEach((key) => {\n if (SENSITIVE_HEADERS.includes(key.toLowerCase())) {\n redacted[key] = \"[REDACTED]\";\n }\n });\n\n return redacted;\n};\n","/**\n * Safely stringifies a value, handling circular references, special types,\n * and non-serializable values.\n * @param {unknown} value - The value to stringify.\n * @param {number} [maxDepth=10] - Maximum depth to traverse objects.\n * @param {boolean} [pretty=false] - Whether to pretty-print the JSON.\n * @returns {string} The safely stringified JSON string.\n */\nexport const safeStringify = (\n value: unknown,\n maxDepth = 10,\n pretty = false\n): string => {\n const seen = new WeakMap<object, true>();\n\n const process = (val: unknown, currentDepth: number): any => {\n if (val === null) return null;\n if (val === undefined) return \"[undefined]\";\n if (typeof val === \"bigint\") return `${val}n`;\n if (typeof val === \"symbol\") return val.toString();\n if (typeof val === \"function\") {\n return `[Function: ${val.name || \"anonymous\"}]`;\n }\n if (typeof val !== \"object\") return val;\n\n if (currentDepth >= maxDepth) {\n return \"[Max Depth]\";\n }\n\n if (seen.has(val)) {\n return \"[Circular]\";\n }\n seen.set(val, true);\n\n if (val instanceof Error) {\n return {\n __type: \"Error\",\n name: val.name,\n message: val.message,\n stack: val.stack,\n };\n }\n\n if (val instanceof Date) {\n return val.toISOString();\n }\n\n if (val instanceof RegExp) {\n return val.toString();\n }\n\n if (val instanceof Map) {\n const obj: Record<string, any> = {};\n val.forEach((v, k) => {\n const key = typeof k === \"string\" ? k : String(k);\n obj[key] = process(v, currentDepth + 1);\n });\n return obj;\n }\n\n if (val instanceof Set) {\n return Array.from(val).map((v) => process(v, currentDepth + 1));\n }\n\n if (ArrayBuffer.isView(val)) {\n return `[${val.constructor.name}(${(val as any).length})]`;\n }\n\n if (Array.isArray(val)) {\n return val.map((item) => process(item, currentDepth + 1));\n }\n\n const result: Record<string, any> = {};\n for (const key in val) {\n if (Object.prototype.hasOwnProperty.call(val, key)) {\n result[key] = process((val as any)[key], currentDepth + 1);\n }\n }\n\n return result;\n };\n\n try {\n const processed = process(value, 0);\n return JSON.stringify(processed, null, pretty ? 2 : 0);\n } catch (error) {\n return JSON.stringify({\n __error: \"Stringification failed\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n};\n","import { BodyFormat, SerializedBody } from \"@/types\";\n\n/**\n * Serializes various body types into a normalized format.\n * Handles JSON, text, FormData, Blob, ArrayBuffer, and others.\n * Returns size estimates and previews for easy display.\n *\n * @param input The body input to serialize\n * @returns SerializedBody object or undefined\n */\nexport const serializeBody = (\n input: any,\n disableBodyCapture?: boolean\n): SerializedBody | undefined => {\n if (disableBodyCapture) {\n return { format: BodyFormat.NONE, size: 0, preview: \"\" };\n }\n\n if (!input) {\n return {\n format: BodyFormat.NONE,\n size: 0,\n preview: \"\",\n };\n }\n\n try {\n // JSON\n if (typeof input === \"object\") {\n const json = JSON.stringify(input);\n return {\n format: BodyFormat.JSON,\n size: json.length,\n preview: json.slice(0, 200),\n raw: json,\n };\n }\n\n // Text\n if (typeof input === \"string\") {\n return {\n format: BodyFormat.TEXT,\n size: input.length,\n preview: input.slice(0, 200),\n raw: input,\n };\n }\n\n // FormData\n if (typeof FormData !== \"undefined\" && input instanceof FormData) {\n return {\n format: BodyFormat.FORM_DATA,\n size: 0,\n preview: \"[FormData]\",\n };\n }\n\n // Blob\n if (typeof Blob !== \"undefined\" && input instanceof Blob) {\n return {\n format: BodyFormat.BLOB,\n size: input.size,\n preview: \"[Blob]\",\n };\n }\n\n // ArrayBuffer\n if (input instanceof ArrayBuffer) {\n return {\n format: BodyFormat.ARRAY_BUFFER,\n size: input.byteLength,\n preview: \"[ArrayBuffer]\",\n };\n }\n\n // Fallback\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: String(input),\n };\n } catch {\n return {\n format: BodyFormat.UNSERIALIZABLE,\n size: 0,\n preview: \"[Unserializable]\",\n };\n }\n};\n","/**\n * Detects if the current environment is a development environment.\n * Supports React Native, Node.js, Vite, and Webpack.\n */\nexport const isDevelopment = (): boolean => {\n try {\n const g = globalThis as any;\n\n // 1. React Native (Hermes/Metro)\n // Check this first as it's the most specific\n if (typeof g.__DEV__ !== \"undefined\") return !!g.__DEV__;\n\n // 2. Node.js / Standard Bundlers\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV) {\n return process.env.NODE_ENV !== \"production\";\n }\n\n /**\n * 3. Vite / Modern ESM\n * We avoid using 'import.meta' literal to prevent Hermes/React Native from\n * throwing a Syntax Error during the parsing phase.\n */\n const importMeta = (g as any).import?.meta;\n if (importMeta?.env?.DEV) {\n return true;\n }\n\n // Fallback for Vite if the above doesn't catch it\n // @ts-ignore\n if (typeof g.import !== \"undefined\" && g.import.meta?.env?.DEV) {\n return true;\n }\n } catch (e) {\n // If anything fails (like a strict CSP), default to true for Dev tools\n return true;\n }\n\n return true;\n};\n","/**\n * Formats a request name based on the URL.\n * * Extracts the last segment of the URL path to use as the request name.\n * * If the URL is invalid, it returns the original URL.\n * * @param {string} url - The URL of the request.\n * * @returns {string} - The formatted request name.\n */\nexport const formatRequestName = (url: string) => {\n try {\n const urlObj = new URL(url);\n const path = urlObj.pathname;\n const segments = path.split(\"/\").filter(Boolean);\n return segments[segments.length - 1] || path || url;\n } catch {\n return url;\n }\n};\n","import { detectConsoleType, detectLogSource, safeStringify } from \"@/helpers\";\nimport {\n ConsoleEvent,\n ConsoleLevel,\n EventType,\n LimelightConfig,\n LimelightMessage,\n} from \"@/types\";\n\nexport class ConsoleInterceptor {\n private originalConsole: Partial<Console> = {};\n private counter = 0;\n private isSetup = false;\n private isInternalLog = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {}\n\n /**\n * Sets up console interception by wrapping console methods.\n * Intercepts log, warn, error, info, debug, trace methods to capture console output.\n * Prevents double setup and infinite loops from internal logging.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Console interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n const methods: ConsoleLevel[] = [\n ConsoleLevel.LOG,\n ConsoleLevel.WARN,\n ConsoleLevel.ERROR,\n ConsoleLevel.INFO,\n ConsoleLevel.DEBUG,\n ConsoleLevel.TRACE,\n ];\n\n methods.forEach((level) => {\n const original = console[level];\n this.originalConsole[level] = original;\n\n console[level] = function (...args: any[]) {\n if (self.isInternalLog) {\n return original.apply(console, args);\n }\n\n self.isInternalLog = true;\n\n try {\n const source = detectLogSource();\n const consoleType = detectConsoleType(level, args);\n const stackTrace = self.captureStackTrace();\n\n let consoleEvent: ConsoleEvent = {\n id: `${self.getSessionId()}-${Date.now()}-${self.counter++}`,\n phase: \"CONSOLE\",\n type: EventType.CONSOLE,\n level: level,\n timestamp: Date.now(),\n sessionId: self.getSessionId(),\n source: source,\n consoleType: consoleType,\n args: args.map((arg) => safeStringify(arg)),\n stackTrace: stackTrace,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(consoleEvent);\n\n if (!modifiedEvent) {\n return original.apply(console, args);\n }\n\n if (modifiedEvent.phase !== \"CONSOLE\") {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return original.apply(console, args);\n }\n\n consoleEvent = modifiedEvent as ConsoleEvent;\n }\n\n self.sendMessage(consoleEvent);\n } catch (error) {\n // Silently fail to avoid breaking user's console.log\n } finally {\n self.isInternalLog = false;\n }\n\n return original.apply(console, args);\n };\n });\n }\n\n /**\n * Captures the current stack trace, filtering out internal frames.\n * @private\n * @returns {string | undefined} Formatted stack trace or undefined if unavailable\n */\n private captureStackTrace(): string | undefined {\n try {\n const error = new Error();\n const stack = error.stack;\n\n if (!stack) return undefined;\n\n const relevantLines = stack\n .split(\"\\n\")\n .slice(3)\n .filter(\n (line) =>\n !line.includes(\"ConsoleInterceptor\") && !line.includes(\"limelight\")\n );\n\n return relevantLines.length > 0 ? relevantLines.join(\"\\n\") : undefined;\n } catch {\n return undefined;\n }\n }\n\n /**\n * Restores original console methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Console interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n Object.entries(this.originalConsole).forEach(([method, fn]) => {\n if (fn) {\n (console as any)[method] = fn;\n }\n });\n\n this.originalConsole = {};\n }\n}\n","/**\n * Generates a unique session ID using the current timestamp and a random string.\n *\n * @return A unique session ID.\n */\nexport const createSessionId = (): string => {\n return `${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n\n/**\n * Generates a unique request ID using the current timestamp and a random string.\n *\n * @return A unique request ID.\n */\nexport const generateRequestId = (): string => {\n return `req-${Date.now()}-${Math.random().toString(36).substring(7)}`;\n};\n","import {\n HttpMethod,\n LimelightConfig,\n LimelightMessage,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkRequest,\n NetworkType,\n} from \"@/types\";\nimport {\n formatRequestName,\n getInitiator,\n isGraphQLRequest,\n parseGraphQL,\n redactSensitiveHeaders,\n serializeBody,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\nexport class NetworkInterceptor {\n private originalFetch: typeof fetch;\n private config: LimelightConfig | null = null;\n private isSetup = false;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalFetch = global.fetch;\n }\n\n /**\n * Sets up fetch interception by wrapping the global fetch function.\n * Intercepts all fetch requests to capture network events.\n * Prevents double setup to avoid losing original fetch reference.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] Network interceptor already set up\");\n return;\n }\n this.isSetup = true;\n\n this.config = config;\n const self = this;\n\n global.fetch = async function (\n input: string | Request | URL,\n init: RequestInit = {}\n ): Promise<Response> {\n const requestId = generateRequestId();\n const startTime = Date.now();\n\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n\n const method = (init.method || \"GET\") as HttpMethod;\n\n const modifiedInit = { ...init };\n\n const headers: Record<string, string> = {};\n\n if (modifiedInit.headers instanceof Headers) {\n modifiedInit.headers.forEach((value, key) => {\n headers[key.toLowerCase()] = value;\n });\n } else if (modifiedInit.headers) {\n Object.entries(modifiedInit.headers).forEach(([key, value]) => {\n headers[key.toLowerCase()] = value;\n });\n }\n\n headers[\"x-limelight-intercepted\"] = \"fetch\";\n\n modifiedInit.headers = new Headers(headers);\n\n let requestBodyToSerialize = init.body;\n\n if (input instanceof Request && !requestBodyToSerialize) {\n try {\n const clonedRequest = input.clone();\n const contentType = clonedRequest.headers.get(\"content-type\") || \"\";\n\n if (\n contentType.includes(\"application/json\") ||\n contentType.includes(\"text/\")\n ) {\n requestBodyToSerialize = await clonedRequest.text();\n } else {\n requestBodyToSerialize = await clonedRequest.blob();\n }\n } catch {\n requestBodyToSerialize = undefined;\n console.warn(\n \"[Limelight] Failed to read request body from Request object\"\n );\n }\n }\n\n const requestBody = serializeBody(\n requestBodyToSerialize,\n self.config?.disableBodyCapture\n );\n\n let graphqlData: NetworkRequest[\"graphql\"] = undefined;\n\n if (self.config?.enableGraphQL && isGraphQLRequest(url, requestBody)) {\n // Pass the raw string to the parser, not the serialized object\n const rawBody = requestBody?.raw;\n if (rawBody) {\n graphqlData = parseGraphQL(rawBody) ?? undefined;\n }\n }\n\n let requestEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.FETCH,\n url,\n method: method,\n headers: redactSensitiveHeaders(headers),\n body: requestBody,\n name: formatRequestName(url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n graphql: graphqlData,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalFetch(input, modifiedInit);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalFetch(input, modifiedInit);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n try {\n const response = await self.originalFetch(input, modifiedInit);\n const clone = response.clone();\n const endTime = Date.now();\n const duration = endTime - startTime;\n const responseHeaders: Record<string, string> = {};\n\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n\n let responseText: string | undefined;\n\n try {\n responseText = await clone.text();\n } catch (cloneError) {\n responseText = undefined;\n }\n\n const responseBody = serializeBody(\n responseText,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.FETCH,\n status: response.status,\n statusText: response.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration,\n responseSize: responseBody?.size ?? 0,\n redirected: response.redirected,\n ok: response.ok,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return response;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return response;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n return response;\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n const errorStack = err instanceof Error ? err.stack : undefined;\n\n let errorEvent: NetworkErrorEvent = {\n id: requestId,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.FETCH,\n errorMessage: errorMessage,\n stack: errorStack,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n\n throw err;\n }\n };\n }\n\n /**\n * Restores the original fetch function and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] Network interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n global.fetch = this.originalFetch;\n }\n}\n","import {\n LimelightConfig,\n LimelightMessage,\n HttpMethod,\n NetworkErrorEvent,\n NetworkPhase,\n NetworkType,\n} from \"@/types\";\nimport {\n redactSensitiveHeaders,\n serializeBody,\n formatRequestName,\n getInitiator,\n} from \"@/helpers\";\nimport { generateRequestId } from \"@/protocol\";\n\ntype XHROpenArgs = Parameters<typeof XMLHttpRequest.prototype.open>;\n\ndeclare global {\n interface XMLHttpRequest {\n _limelightData?: {\n id: string;\n method: string;\n url: string;\n headers: Record<string, string>;\n startTime: number;\n skipIntercept?: boolean;\n listeners?: Map<string, EventListener>;\n };\n }\n}\n\nexport class XHRInterceptor {\n private originalXHROpen: typeof XMLHttpRequest.prototype.open;\n private originalXHRSend: typeof XMLHttpRequest.prototype.send;\n private originalXHRSetRequestHeader: typeof XMLHttpRequest.prototype.setRequestHeader;\n\n private isSetup = false;\n private config: LimelightConfig | null = null;\n\n constructor(\n private sendMessage: (message: LimelightMessage) => void,\n private getSessionId: () => string\n ) {\n this.originalXHROpen = XMLHttpRequest.prototype.open;\n this.originalXHRSend = XMLHttpRequest.prototype.send;\n this.originalXHRSetRequestHeader =\n XMLHttpRequest.prototype.setRequestHeader;\n }\n\n /**\n * Sets up XHR interception by wrapping XMLHttpRequest methods.\n * Intercepts open, setRequestHeader, and send to capture network events.\n * Prevents double setup to avoid losing original method references.\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n setup(config: LimelightConfig) {\n if (this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor already set up\");\n return;\n }\n this.isSetup = true;\n this.config = config;\n\n const self = this;\n\n XMLHttpRequest.prototype.open = function (method: string, url: string) {\n this._limelightData = {\n id: generateRequestId(),\n method,\n url,\n headers: {},\n startTime: Date.now(),\n listeners: new Map(),\n };\n\n return self.originalXHROpen.apply(\n this,\n arguments as unknown as XHROpenArgs\n );\n };\n\n XMLHttpRequest.prototype.setRequestHeader = function (\n header: string,\n value: string\n ) {\n if (this._limelightData) {\n this._limelightData.headers[header] = value;\n\n if (\n header.toLowerCase() === \"x-limelight-intercepted\" &&\n value === \"fetch\"\n ) {\n this._limelightData.skipIntercept = true;\n }\n }\n\n return self.originalXHRSetRequestHeader.apply(this, arguments as any);\n };\n\n XMLHttpRequest.prototype.send = function (body) {\n const data = this._limelightData;\n\n if (data?.skipIntercept) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (data) {\n const requestBody = serializeBody(\n body,\n self.config?.disableBodyCapture\n );\n\n let requestEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: data.startTime,\n phase: NetworkPhase.REQUEST,\n networkType: NetworkType.XHR,\n url: data.url,\n method: data.method as HttpMethod,\n headers: redactSensitiveHeaders(data.headers),\n body: requestBody,\n name: formatRequestName(data.url),\n initiator: getInitiator(),\n requestSize: requestBody?.size ?? 0,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(requestEvent);\n\n if (!modifiedEvent) {\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n if (modifiedEvent.phase !== NetworkPhase.REQUEST) {\n console.error(\"[Limelight] beforeSend must return same event type\");\n return self.originalXHRSend.apply(this, arguments as any);\n }\n\n requestEvent = modifiedEvent;\n }\n\n self.sendMessage(requestEvent);\n\n let responseSent = false;\n\n /**\n * Removes all event listeners and cleans up after request completion.\n */\n const cleanup = () => {\n if (data.listeners) {\n data.listeners.forEach((listener, event) => {\n this.removeEventListener(event, listener);\n });\n data.listeners.clear();\n }\n // Clear the data to allow GC\n delete this._limelightData;\n };\n\n /**\n * Sends the response event.\n * Ensures response is only sent once using responseSent flag.\n */\n const sendResponse = () => {\n if (responseSent) return;\n responseSent = true;\n\n const endTime = Date.now();\n const duration = endTime - data.startTime;\n const responseHeaders = self.parseResponseHeaders(\n this.getAllResponseHeaders()\n );\n\n const responseBody = serializeBody(\n this.responseText || this.response,\n self.config?.disableBodyCapture\n );\n\n let responseEvent: LimelightMessage = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: endTime,\n phase: NetworkPhase.RESPONSE,\n networkType: NetworkType.XHR,\n status: this.status,\n statusText: this.statusText,\n headers: redactSensitiveHeaders(responseHeaders),\n body: responseBody,\n duration: duration,\n responseSize: responseBody?.size ?? 0,\n redirected: false,\n ok: this.status >= 200 && this.status < 300,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(responseEvent);\n\n if (!modifiedEvent) {\n return;\n }\n\n if (modifiedEvent.phase !== NetworkPhase.RESPONSE) {\n console.error(\n \"[Limelight] beforeSend must return same event type\"\n );\n return;\n }\n\n responseEvent = modifiedEvent;\n }\n\n self.sendMessage(responseEvent);\n cleanup.call(this);\n };\n\n /**\n * Sends an error event.\n * Also sets responseSent to prevent duplicate response events.\n */\n const sendError = (errorMessage: string) => {\n if (responseSent) return;\n responseSent = true;\n\n let errorEvent: NetworkErrorEvent = {\n id: data.id,\n sessionId: self.getSessionId(),\n timestamp: Date.now(),\n phase: NetworkPhase.ERROR,\n networkType: NetworkType.XHR,\n errorMessage: errorMessage,\n };\n\n if (self.config?.beforeSend) {\n const modifiedEvent = self.config.beforeSend(errorEvent);\n\n if (modifiedEvent && modifiedEvent.phase === NetworkPhase.ERROR) {\n errorEvent = modifiedEvent;\n }\n }\n\n self.sendMessage(errorEvent);\n cleanup.call(this);\n };\n\n const readyStateChangeHandler = function (this: XMLHttpRequest) {\n if (\n (this.readyState === 3 || this.readyState === 4) &&\n this.status !== 0\n ) {\n sendResponse.call(this);\n }\n };\n\n const loadHandler = function (this: XMLHttpRequest) {\n sendResponse.call(this);\n };\n\n const errorHandler = function (this: XMLHttpRequest) {\n sendError(\"Network request failed\");\n cleanup.call(this);\n };\n\n const abortHandler = function (this: XMLHttpRequest) {\n sendError(\"Request aborted\");\n cleanup.call(this);\n };\n\n const timeoutHandler = function (this: XMLHttpRequest) {\n sendError(\"Request timeout\");\n cleanup.call(this);\n };\n\n const loadEndHandler = function (this: XMLHttpRequest) {\n cleanup.call(this);\n };\n\n this.addEventListener(\"readystatechange\", readyStateChangeHandler);\n this.addEventListener(\"load\", loadHandler);\n this.addEventListener(\"error\", errorHandler);\n this.addEventListener(\"abort\", abortHandler);\n this.addEventListener(\"timeout\", timeoutHandler);\n this.addEventListener(\"loadend\", loadEndHandler);\n\n data.listeners!.set(\"readystatechange\", readyStateChangeHandler);\n data.listeners!.set(\"load\", loadHandler);\n data.listeners!.set(\"error\", errorHandler);\n data.listeners!.set(\"abort\", abortHandler);\n data.listeners!.set(\"timeout\", timeoutHandler);\n data.listeners!.set(\"loadend\", loadEndHandler);\n }\n\n return self.originalXHRSend.apply(this, arguments as any);\n };\n }\n\n /**\n * Parses raw HTTP header string into a key-value object.\n * @private\n * @param {string} headerString - Raw header string from getAllResponseHeaders()\n * @returns {Record<string, string>} Parsed headers object\n */\n private parseResponseHeaders(headerString: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n headerString.split(\"\\r\\n\").forEach((line) => {\n const colonIndex = line.indexOf(\": \");\n if (colonIndex > 0) {\n const key = line.substring(0, colonIndex);\n const value = line.substring(colonIndex + 2);\n headers[key] = value;\n }\n });\n\n return headers;\n }\n\n /**\n * Restores original XMLHttpRequest methods and removes all interception.\n * @returns {void}\n */\n cleanup() {\n if (!this.isSetup) {\n console.warn(\"[Limelight] XHR interceptor not set up\");\n return;\n }\n this.isSetup = false;\n\n XMLHttpRequest.prototype.open = this.originalXHROpen;\n XMLHttpRequest.prototype.send = this.originalXHRSend;\n XMLHttpRequest.prototype.setRequestHeader =\n this.originalXHRSetRequestHeader;\n }\n}\n","import { LimelightConfig, LimelightMessage } from \"@/types\";\nimport {\n ConsoleInterceptor,\n NetworkInterceptor,\n XHRInterceptor,\n} from \"@/limelight/interceptors\";\nimport { isDevelopment, safeStringify } from \"@/helpers\";\nimport { DEFAULT_PORT, SDK_VERSION, WS_PATH } from \"@/constants\";\nimport { createSessionId } from \"@/protocol\";\n\nclass LimelightClient {\n private ws: WebSocket | null = null;\n private config: LimelightConfig | null = null;\n private sessionId: string = \"\";\n\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private reconnectDelay = 1000;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n\n private messageQueue: LimelightMessage[] = [];\n private maxQueueSize = 100;\n\n private networkInterceptor: NetworkInterceptor;\n private xhrInterceptor: XHRInterceptor;\n private consoleInterceptor: ConsoleInterceptor;\n\n constructor() {\n this.networkInterceptor = new NetworkInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.xhrInterceptor = new XHRInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n this.consoleInterceptor = new ConsoleInterceptor(\n this.sendMessage.bind(this),\n () => this.sessionId\n );\n }\n\n /**\n * Configures the Limelight client with the provided settings.\n * Sets up network, XHR, and console interceptors based on the configuration.\n * @internal\n * @private\n * @param {LimelightConfig} config - Configuration object for Limelight\n * @returns {void}\n */\n private configure(config: LimelightConfig) {\n const isEnabled = config.enabled ?? isDevelopment();\n\n this.config = {\n appName: \"Limelight App\",\n serverUrl: `ws://localhost:${DEFAULT_PORT}${WS_PATH}`,\n enabled: isEnabled,\n enableNetworkInspector: true,\n enableConsole: true,\n enableGraphQL: true,\n ...config,\n };\n\n if (!this.config.enabled) {\n return;\n }\n\n this.sessionId = createSessionId();\n\n try {\n if (this.config.enableNetworkInspector) {\n this.networkInterceptor.setup(this.config);\n this.xhrInterceptor.setup(this.config);\n }\n\n if (this.config.enableConsole) {\n this.consoleInterceptor.setup(this.config);\n }\n } catch (error) {\n console.error(\"[Limelight] Failed to setup interceptors:\", error);\n }\n }\n\n /**\n * Establishes a WebSocket connection to the Limelight server.\n * If a config object is provided, it will configure the client before connecting.\n *\n * If no config is provided and the client hasn't been configured, it will use default settings.\n *\n * Prevents multiple simultaneous connections and handles reconnection logic.\n *\n * @param {LimelightConfig} [config] - Optional configuration object.\n * @returns {void}\n */\n connect(config: LimelightConfig) {\n if (config) {\n this.configure(config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n\n if (!this.config?.enabled) {\n return;\n }\n\n if (this.ws && this.ws.readyState === WebSocket.OPEN) {\n console.warn(\"[Limelight] Already connected. Call disconnect() first.\");\n return;\n }\n\n if (this.ws) {\n const oldWs = this.ws;\n\n oldWs.onclose = null;\n oldWs.onerror = null;\n oldWs.onopen = null;\n\n // 1 is OPEN\n if (oldWs.readyState === 1) {\n oldWs.close();\n }\n\n this.ws = null;\n }\n const { serverUrl, appName, platform } = this.config;\n\n if (!serverUrl) {\n console.error(\"[Limelight] serverUrl missing in configuration.\");\n return;\n }\n\n try {\n this.ws = new WebSocket(serverUrl);\n\n const message: LimelightMessage = {\n phase: \"CONNECT\",\n sessionId: this.sessionId,\n timestamp: Date.now(),\n data: {\n appName: appName,\n platform:\n platform ||\n (typeof window !== \"undefined\" ? \"web\" : \"react-native\"),\n projectKey: this.config.projectKey,\n sdkVersion: SDK_VERSION,\n },\n };\n\n this.ws.onopen = () => {\n this.reconnectAttempts = 0;\n this.flushMessageQueue();\n this.sendMessage(message);\n };\n\n this.ws.onerror = (error) => {\n console.error(\"[Limelight] WebSocket error:\", error);\n };\n\n this.ws.onclose = () => {\n this.attemptReconnect();\n };\n } catch (error) {\n console.error(\"[Limelight] Failed to connect:\", error);\n this.attemptReconnect();\n }\n }\n\n /**\n * Attempts to reconnect to the Limelight server using exponential backoff.\n * Will retry up to maxReconnectAttempts times with increasing delays.\n * Maximum delay is capped at 30 seconds.\n * @private\n * @returns {void}\n */\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n return;\n }\n\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.reconnectAttempts++;\n const delay = Math.min(\n this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1),\n 30000\n );\n\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n\n if (this.config) {\n this.configure(this.config);\n } else if (!this.config) {\n throw new Error(\n \"[Limelight] Limelight not configured. Please provide a configuration object when calling connect(). Project id is the only required field.\"\n );\n }\n }, delay);\n }\n\n /**\n * Sends all queued messages to the server.\n * Only executes if the WebSocket connection is open.\n * @private\n * @returns {void}\n */\n private flushMessageQueue() {\n if (this.ws?.readyState !== WebSocket.OPEN) return;\n\n while (this.messageQueue.length > 0) {\n const message = this.messageQueue.shift();\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send queued message:\", error);\n }\n }\n }\n\n /**\n * Sends a message to the Limelight server or queues it if not connected.\n * Messages are automatically queued when the connection is not open.\n * If the queue is full, the oldest message will be dropped.\n * @private\n * @param {LimelightMessage} message - The message to send\n * @returns {void}\n */\n private sendMessage(message: LimelightMessage) {\n if (this.ws?.readyState === WebSocket.OPEN) {\n this.flushMessageQueue();\n\n if (this.ws?.readyState === WebSocket.OPEN) {\n try {\n this.ws.send(safeStringify(message));\n } catch (error) {\n console.error(\"[Limelight] Failed to send message:\", error);\n this.messageQueue.push(message);\n }\n } else {\n this.messageQueue.push(message);\n }\n } else {\n if (this.messageQueue.length >= this.maxQueueSize) {\n console.warn(\"[Limelight] Message queue full, dropping oldest message\");\n this.messageQueue.shift();\n }\n this.messageQueue.push(message);\n }\n }\n\n /**\n * Disconnects from the Limelight server and cleans up resources.\n * Closes the WebSocket connection, removes all interceptors, and resets connection state.\n * Preserves configuration and session ID for potential reconnection.\n * @returns {void}\n */\n disconnect() {\n if (this.ws) {\n // 1. Detach all listeners first so no logic runs after this\n this.ws.onopen = null;\n this.ws.onerror = null;\n this.ws.onclose = null;\n\n try {\n // 2. Only attempt to close if it's not already closed/closing\n if (this.ws.readyState === 0 || this.ws.readyState === 1) {\n // We use terminate if available (Node ws), otherwise close (Browser)\n if (\n \"terminate\" in this.ws &&\n typeof (this.ws as any).terminate === \"function\"\n ) {\n // For Node ws: check if socket exists before terminating\n // This prevents \"closed before established\" errors\n if ((this.ws as any)._socket) {\n (this.ws as any).terminate();\n } else {\n // If socket doesn't exist yet, just set readyState to CLOSED\n // to prevent the connection from completing\n (this.ws as any).readyState = 3; // CLOSED\n }\n } else {\n this.ws.close();\n }\n }\n } catch (e) {\n // Silently ignore WebSocket closure errors during cleanup\n }\n\n this.ws = null;\n }\n\n // Clear timers and interceptors...\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n\n this.networkInterceptor.cleanup();\n this.xhrInterceptor.cleanup();\n this.consoleInterceptor.cleanup();\n\n this.reconnectAttempts = 0;\n this.messageQueue = [];\n }\n\n /**\n * Performs a complete reset of the Limelight client.\n * Disconnects from the server and clears all configuration and session data.\n * After calling reset(), connect() must be called again.\n * @returns {void}\n */\n reset() {\n this.disconnect();\n this.config = null;\n this.sessionId = \"\";\n }\n}\n\nexport const Limelight = new LimelightClient();\nexport { LimelightClient };\n"],"mappings":"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","names":["ConsoleLevel","ConsoleSource","ConsoleType","NetworkType","NetworkPhase","BodyFormat","HttpMethod","HttpStatusClass","EventType","GraphqlOprtation","process"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getlimelight/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "The react native debugger that actually works",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",