@thaparoyal/replayapi 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ var originalHttpRequest = null;
65
65
  var originalHttpGet = null;
66
66
  var originalHttpsRequest = null;
67
67
  var originalHttpsGet = null;
68
- var PROXY_URL = "http://localhost:8080";
68
+ var PROXY_URL = process.env.REPLAY_PROXY_URL || "http://localhost:8080";
69
69
  var active = false;
70
70
  var config;
71
71
  var stats = {
@@ -244,7 +244,7 @@ function getHttpStats() {
244
244
  }
245
245
 
246
246
  // src/interceptor-fetch.ts
247
- var PROXY_URL2 = "http://localhost:8080";
247
+ var PROXY_URL2 = process.env.REPLAY_PROXY_URL || "http://localhost:8080";
248
248
  var originalFetch = null;
249
249
  var active2 = false;
250
250
  var config2;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/matcher.ts","../src/logger.ts","../src/interceptor-http.ts","../src/interceptor-fetch.ts","../src/index.ts"],"names":["URL","https","http","PROXY_URL","active","config","stats","init"],"mappings":"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","file":"index.js","sourcesContent":["/**\r\n * ReplayAPI SDK — URL matching utilities\r\n */\r\n\r\n/**\r\n * Check if a URL matches any of the given patterns.\r\n * Patterns can be strings (substring match) or RegExp.\r\n */\r\nexport function matchesPatterns(\r\n url: string,\r\n patterns: Array<string | RegExp>\r\n): boolean {\r\n return patterns.some((pattern) => {\r\n if (typeof pattern === \"string\") {\r\n return url.includes(pattern);\r\n }\r\n return pattern.test(url);\r\n });\r\n}\r\n\r\n/**\r\n * Determine if a request URL should be captured based on include/exclude filters.\r\n */\r\nexport function shouldCapture(\r\n url: string,\r\n proxyUrl: string,\r\n include?: Array<string | RegExp>,\r\n exclude?: Array<string | RegExp>\r\n): boolean {\r\n // Never capture requests to the proxy itself\r\n if (url.startsWith(proxyUrl)) {\r\n return false;\r\n }\r\n\r\n // Never capture requests to ReplayAPI internal paths\r\n if (url.includes(\"/__replay/\")) {\r\n return false;\r\n }\r\n\r\n // If include patterns are set, URL must match at least one\r\n if (include && include.length > 0) {\r\n if (!matchesPatterns(url, include)) {\r\n return false;\r\n }\r\n }\r\n\r\n // If exclude patterns are set, URL must not match any\r\n if (exclude && exclude.length > 0) {\r\n if (matchesPatterns(url, exclude)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * ReplayAPI SDK — Simple logger\r\n */\r\n\r\nlet debugEnabled = false;\r\n\r\nexport function setDebug(enabled: boolean): void {\r\n debugEnabled = enabled;\r\n}\r\n\r\nexport function debug(...args: unknown[]): void {\r\n if (debugEnabled) {\r\n console.log(\"[replayapi]\", ...args);\r\n }\r\n}\r\n\r\nexport function info(...args: unknown[]): void {\r\n console.log(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function warn(...args: unknown[]): void {\r\n console.warn(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function error(...args: unknown[]): void {\r\n console.error(\"[replayapi]\", ...args);\r\n}\r\n","/**\r\n * ReplayAPI SDK — HTTP/HTTPS interceptor\r\n *\r\n * Monkey-patches Node.js http.request and https.request to redirect\r\n * outgoing requests through the ReplayAPI proxy. The proxy captures\r\n * the traffic and forwards it to the original target.\r\n *\r\n * How it works:\r\n * 1. Original request: GET https://api.example.com/users\r\n * 2. SDK rewrites to: GET http://proxy:8080/users\r\n * with headers:\r\n * X-Api-Key: rp_...\r\n * X-Replay-Target: https://api.example.com\r\n * X-Replay-Env: staging\r\n * 3. Proxy captures, forwards to target, returns response transparently\r\n */\r\n\r\nimport http from \"node:http\";\r\nimport https from \"node:https\";\r\nimport { URL } from \"node:url\";\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\n// Store original implementations\r\nlet originalHttpRequest: typeof http.request | null = null;\r\nlet originalHttpGet: typeof http.get | null = null;\r\nlet originalHttpsRequest: typeof https.request | null = null;\r\nlet originalHttpsGet: typeof https.get | null = null;\r\n\r\nconst PROXY_URL = \"http://localhost:8080\";\r\n\r\n// Track state\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Parse the various argument formats that http.request accepts:\r\n * - (url: string, options?, callback?)\r\n * - (url: URL, options?, callback?)\r\n * - (options, callback?)\r\n */\r\nfunction parseRequestArgs(\r\n args: unknown[]\r\n): {\r\n targetUrl: string;\r\n options: http.RequestOptions;\r\n callback?: (res: http.IncomingMessage) => void;\r\n} {\r\n let targetUrl: string;\r\n let options: http.RequestOptions = {};\r\n let callback: ((res: http.IncomingMessage) => void) | undefined;\r\n\r\n if (typeof args[0] === \"string\") {\r\n targetUrl = args[0];\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (args[0] instanceof URL) {\r\n targetUrl = args[0].toString();\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\r\n options = args[0] as http.RequestOptions;\r\n const protocol = (options as { protocol?: string }).protocol || \"http:\";\r\n const host = options.hostname || options.host || \"localhost\";\r\n const port = options.port ? `:${options.port}` : \"\";\r\n const path = options.path || \"/\";\r\n targetUrl = `${protocol}//${host}${port}${path}`;\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n }\r\n } else {\r\n targetUrl = \"\";\r\n }\r\n\r\n return { targetUrl, options, callback };\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.request / https.request\r\n */\r\nfunction createProxiedRequest(\r\n originalFn: typeof http.request,\r\n defaultProtocol: \"http:\" | \"https:\"\r\n): typeof http.request {\r\n return function proxiedRequest(\r\n ...args: unknown[]\r\n ): http.ClientRequest {\r\n try {\r\n const { targetUrl, options, callback } = parseRequestArgs(args);\r\n\r\n if (!targetUrl) {\r\n log.debug(\"could not parse request URL, passing through\");\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Parse the proxy URL\r\n const proxyParsed = new URL(config.proxyUrl);\r\n\r\n // Parse the target URL to extract origin and path\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n\r\n // Build proxied options: send to proxy, with X-Replay-Target header\r\n const proxiedOptions: http.RequestOptions = {\r\n ...options,\r\n protocol: proxyParsed.protocol,\r\n hostname: proxyParsed.hostname,\r\n port: proxyParsed.port || (proxyParsed.protocol === \"https:\" ? 443 : 80),\r\n path: parsedTarget.pathname + parsedTarget.search,\r\n headers: {\r\n ...options.headers,\r\n \"X-Api-Key\": config.apiKey,\r\n \"X-Replay-Target\": targetOrigin,\r\n \"X-Replay-Env\": config.environment,\r\n // Preserve the original Host header\r\n Host: parsedTarget.host,\r\n },\r\n };\r\n\r\n // Add session ID if configured\r\n if (config.sessionId) {\r\n (proxiedOptions.headers as Record<string, string>)[\"X-Replay-Session\"] =\r\n config.sessionId;\r\n }\r\n\r\n // Set timeout if configured\r\n if (config.timeout) {\r\n proxiedOptions.timeout = config.timeout;\r\n }\r\n\r\n log.debug(\"capturing:\", options.method || \"GET\", targetUrl, \"→\", config.proxyUrl);\r\n stats.totalCaptured++;\r\n\r\n // Use http.request (not https) since we're talking to the proxy over HTTP\r\n const proxyUrl = new URL(`${proxiedOptions.protocol}//${proxiedOptions.hostname}:${proxiedOptions.port}${proxiedOptions.path}`);\r\n return originalHttpRequest!.call(http, proxyUrl, proxiedOptions, callback);\r\n } catch (err) {\r\n log.error(\"interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n } as typeof http.request;\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.get / https.get\r\n */\r\nfunction createProxiedGet(\r\n proxiedRequest: typeof http.request\r\n): typeof http.get {\r\n return function proxiedGet(...args: unknown[]): http.ClientRequest {\r\n const req = (proxiedRequest as Function)(...args) as http.ClientRequest;\r\n req.end();\r\n return req;\r\n } as typeof http.get;\r\n}\r\n\r\n/**\r\n * Install the HTTP/HTTPS interceptors\r\n */\r\nexport function installHttpInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"interceptor already installed, call stop() first\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n // Save originals\r\n originalHttpRequest = http.request;\r\n originalHttpGet = http.get;\r\n originalHttpsRequest = https.request;\r\n originalHttpsGet = https.get;\r\n\r\n // Patch http\r\n const proxiedHttpRequest = createProxiedRequest(originalHttpRequest, \"http:\");\r\n http.request = proxiedHttpRequest;\r\n http.get = createProxiedGet(proxiedHttpRequest);\r\n\r\n // Patch https\r\n const proxiedHttpsRequest = createProxiedRequest(\r\n originalHttpsRequest,\r\n \"https:\"\r\n );\r\n https.request = proxiedHttpsRequest;\r\n https.get = createProxiedGet(proxiedHttpsRequest);\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"http/https interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the HTTP/HTTPS interceptors\r\n */\r\nexport function uninstallHttpInterceptor(): void {\r\n if (!active) return;\r\n\r\n if (originalHttpRequest) http.request = originalHttpRequest;\r\n if (originalHttpGet) http.get = originalHttpGet;\r\n if (originalHttpsRequest) https.request = originalHttpsRequest;\r\n if (originalHttpsGet) https.get = originalHttpsGet;\r\n\r\n originalHttpRequest = null;\r\n originalHttpGet = null;\r\n originalHttpsRequest = null;\r\n originalHttpsGet = null;\r\n\r\n active = false;\r\n log.debug(\"http/https interceptor removed\");\r\n}\r\n\r\nexport function isHttpInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getHttpStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * ReplayAPI SDK — Global fetch() interceptor\r\n *\r\n * Patches globalThis.fetch to route requests through the ReplayAPI proxy.\r\n * Works with Node.js 18+ native fetch and any polyfills that set globalThis.fetch.\r\n */\r\n\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nconst PROXY_URL = \"http://localhost:8080\";\r\n\r\nlet originalFetch: typeof globalThis.fetch | null = null;\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Install the fetch interceptor\r\n */\r\nexport function installFetchInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"fetch interceptor already installed\");\r\n return;\r\n }\r\n\r\n // Only patch if fetch exists (Node.js 18+)\r\n if (typeof globalThis.fetch !== \"function\") {\r\n log.debug(\"globalThis.fetch not available, skipping fetch interceptor\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n originalFetch = globalThis.fetch;\r\n\r\n globalThis.fetch = async function proxiedFetch(\r\n input: string | URL | Request,\r\n init?: RequestInit\r\n ): Promise<Response> {\r\n try {\r\n // Resolve the target URL\r\n let targetUrl: string;\r\n if (typeof input === \"string\") {\r\n targetUrl = input;\r\n } else if (input instanceof URL) {\r\n targetUrl = input.toString();\r\n } else if (input instanceof Request) {\r\n targetUrl = input.url;\r\n } else {\r\n targetUrl = String(input);\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"fetch skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n // Parse target URL\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"fetch: invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n const proxyPath = parsedTarget.pathname + parsedTarget.search;\r\n const proxiedUrl = `${config.proxyUrl}${proxyPath}`;\r\n\r\n // Build headers\r\n const headers = new Headers(init?.headers || {});\r\n\r\n // If input is a Request, merge its headers too\r\n if (input instanceof Request) {\r\n input.headers.forEach((value, key) => {\r\n if (!headers.has(key)) {\r\n headers.set(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Add ReplayAPI headers\r\n headers.set(\"X-Api-Key\", config.apiKey);\r\n headers.set(\"X-Replay-Target\", targetOrigin);\r\n headers.set(\"X-Replay-Env\", config.environment);\r\n headers.set(\"Host\", parsedTarget.host);\r\n\r\n if (config.sessionId) {\r\n headers.set(\"X-Replay-Session\", config.sessionId);\r\n }\r\n\r\n // Build proxied init\r\n const proxiedInit: RequestInit = {\r\n ...init,\r\n headers,\r\n };\r\n\r\n // If input is a Request, preserve method and body\r\n if (input instanceof Request) {\r\n proxiedInit.method = proxiedInit.method || input.method;\r\n if (!proxiedInit.body && input.body) {\r\n proxiedInit.body = input.body;\r\n }\r\n }\r\n\r\n log.debug(\r\n \"fetch capturing:\",\r\n proxiedInit.method || \"GET\",\r\n targetUrl,\r\n \"→\",\r\n config.proxyUrl\r\n );\r\n stats.totalCaptured++;\r\n\r\n return originalFetch!(proxiedUrl, proxiedInit);\r\n } catch (err) {\r\n log.error(\"fetch interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return originalFetch!(input, init);\r\n }\r\n };\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"fetch interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the fetch interceptor\r\n */\r\nexport function uninstallFetchInterceptor(): void {\r\n if (!active || !originalFetch) return;\r\n\r\n globalThis.fetch = originalFetch;\r\n originalFetch = null;\r\n active = false;\r\n log.debug(\"fetch interceptor removed\");\r\n}\r\n\r\nexport function isFetchInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getFetchStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * @replayapi/node — ReplayAPI SDK for Node.js\r\n *\r\n * Automatically captures outgoing HTTP traffic and routes it through\r\n * the ReplayAPI proxy for recording, analysis, and replay testing.\r\n *\r\n * @example\r\n * ```ts\r\n * import { replayApi } from '@replayapi/node'\r\n *\r\n * // Simplest — just pass your API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: 'rp_your_api_key', environment: 'staging' })\r\n *\r\n * // All outgoing HTTP/fetch calls are now captured automatically\r\n * ```\r\n */\r\n\r\nimport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\nimport {\r\n installHttpInterceptor,\r\n uninstallHttpInterceptor,\r\n isHttpInterceptorActive,\r\n getHttpStats,\r\n} from \"./interceptor-http.js\";\r\nimport {\r\n installFetchInterceptor,\r\n uninstallFetchInterceptor,\r\n isFetchInterceptorActive,\r\n getFetchStats,\r\n} from \"./interceptor-fetch.js\";\r\nimport { setDebug } from \"./logger.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nlet initialized = false;\r\n\r\n/**\r\n * Initialize the ReplayAPI SDK.\r\n *\r\n * Call this once at application startup, before any outgoing HTTP requests.\r\n * The SDK will automatically intercept `http.request`, `https.request`,\r\n * and `fetch` to route traffic through the ReplayAPI proxy.\r\n *\r\n * @example\r\n * ```ts\r\n * // Just an API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: process.env.REPLAY_API_KEY!, environment: 'staging' })\r\n * ```\r\n */\r\nfunction init(configOrApiKey: ReplayApiConfig | string): ReplayApiInstance {\r\n // Accept a plain string as shorthand for { apiKey: string }\r\n const config: ReplayApiConfig =\r\n typeof configOrApiKey === \"string\" ? { apiKey: configOrApiKey } : configOrApiKey;\r\n\r\n if (initialized) {\r\n log.warn(\"replayApi.init() called multiple times — stopping previous instance\");\r\n stop();\r\n }\r\n\r\n // Validate config\r\n if (!config.apiKey) {\r\n throw new Error(\r\n \"[@replayapi/node] apiKey is required. Get one from your ReplayAPI dashboard.\"\r\n );\r\n }\r\n\r\n if (config.disabled) {\r\n log.info(\"SDK disabled via config, skipping initialization\");\r\n return { stop, isActive, getStats };\r\n }\r\n\r\n // Enable debug logging if requested\r\n if (config.debug) {\r\n setDebug(true);\r\n }\r\n\r\n // Resolve environment with env var fallback\r\n config.environment =\r\n config.environment || process.env.REPLAY_ENVIRONMENT || \"development\";\r\n\r\n log.info(`initialized — env: ${config.environment}`);\r\n\r\n // Install interceptors\r\n installHttpInterceptor(config);\r\n installFetchInterceptor(config);\r\n\r\n initialized = true;\r\n\r\n return { stop, isActive, getStats };\r\n}\r\n\r\n/**\r\n * Stop the SDK and restore original HTTP/fetch behavior.\r\n */\r\nfunction stop(): void {\r\n if (!initialized) return;\r\n\r\n uninstallHttpInterceptor();\r\n uninstallFetchInterceptor();\r\n\r\n initialized = false;\r\n log.info(\"stopped — all interceptors removed\");\r\n}\r\n\r\n/**\r\n * Check if the SDK is currently intercepting traffic.\r\n */\r\nfunction isActive(): boolean {\r\n return isHttpInterceptorActive() || isFetchInterceptorActive();\r\n}\r\n\r\n/**\r\n * Get combined capture statistics from all interceptors.\r\n */\r\nfunction getStats(): CaptureStats {\r\n const httpStats = getHttpStats();\r\n const fetchStats = getFetchStats();\r\n\r\n return {\r\n totalCaptured: httpStats.totalCaptured + fetchStats.totalCaptured,\r\n totalSkipped: httpStats.totalSkipped + fetchStats.totalSkipped,\r\n totalErrors: httpStats.totalErrors + fetchStats.totalErrors,\r\n startedAt: httpStats.startedAt < fetchStats.startedAt\r\n ? httpStats.startedAt\r\n : fetchStats.startedAt,\r\n };\r\n}\r\n\r\n/**\r\n * The main ReplayAPI SDK instance.\r\n */\r\nexport const replayApi = {\r\n init,\r\n stop,\r\n isActive,\r\n getStats,\r\n};\r\n\r\n// Named exports for flexibility\r\nexport { init, stop, isActive, getStats };\r\n\r\n// Re-export types\r\nexport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\n"]}
1
+ {"version":3,"sources":["../src/matcher.ts","../src/logger.ts","../src/interceptor-http.ts","../src/interceptor-fetch.ts","../src/index.ts"],"names":["URL","https","http","PROXY_URL","active","config","stats","init"],"mappings":";;;;;;;;;;;;;;AAQO,SAAS,eAAA,CACd,KACA,QAAA,EACS;AACT,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,CAAC,OAAA,KAAY;AAChC,IAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,MAAA,OAAO,GAAA,CAAI,SAAS,OAAO,CAAA;AAAA,IAC7B;AACA,IAAA,OAAO,OAAA,CAAQ,KAAK,GAAG,CAAA;AAAA,EACzB,CAAC,CAAA;AACH;AAKO,SAAS,aAAA,CACd,GAAA,EACA,QAAA,EACA,OAAA,EACA,OAAA,EACS;AAET,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,QAAQ,CAAA,EAAG;AAC5B,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,GAAA,CAAI,QAAA,CAAS,YAAY,CAAA,EAAG;AAC9B,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACjC,IAAA,IAAI,CAAC,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG;AAClC,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACjC,IAAA,IAAI,eAAA,CAAgB,GAAA,EAAK,OAAO,CAAA,EAAG;AACjC,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;;;AClDA,IAAI,YAAA,GAAe,KAAA;AAEZ,SAAS,SAAS,OAAA,EAAwB;AAC/C,EAAA,YAAA,GAAe,OAAA;AACjB;AAEO,SAAS,SAAS,IAAA,EAAuB;AAC9C,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe,GAAG,IAAI,CAAA;AAAA,EACpC;AACF;AAEO,SAAS,QAAQ,IAAA,EAAuB;AAC7C,EAAA,OAAA,CAAQ,GAAA,CAAI,aAAA,EAAe,GAAG,IAAI,CAAA;AACpC;AAEO,SAAS,QAAQ,IAAA,EAAuB;AAC7C,EAAA,OAAA,CAAQ,IAAA,CAAK,aAAA,EAAe,GAAG,IAAI,CAAA;AACrC;AAEO,SAAS,SAAS,IAAA,EAAuB;AAC9C,EAAA,OAAA,CAAQ,KAAA,CAAM,aAAA,EAAe,GAAG,IAAI,CAAA;AACtC;;;ACDA,IAAI,mBAAA,GAAkD,IAAA;AACtD,IAAI,eAAA,GAA0C,IAAA;AAC9C,IAAI,oBAAA,GAAoD,IAAA;AACxD,IAAI,gBAAA,GAA4C,IAAA;AAEhD,IAAM,SAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,gBAAA,IAAoB,uBAAA;AAGlD,IAAI,MAAA,GAAS,KAAA;AACb,IAAI,MAAA;AAKJ,IAAM,KAAA,GAAsB;AAAA,EAC1B,aAAA,EAAe,CAAA;AAAA,EACf,YAAA,EAAc,CAAA;AAAA,EACd,WAAA,EAAa,CAAA;AAAA,EACb,SAAA,sBAAe,IAAA;AACjB,CAAA;AAQA,SAAS,iBACP,IAAA,EAKA;AACA,EAAA,IAAI,SAAA;AACJ,EAAA,IAAI,UAA+B,EAAC;AACpC,EAAA,IAAI,QAAA;AAEJ,EAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,QAAA,EAAU;AAC/B,IAAA,SAAA,GAAY,KAAK,CAAC,CAAA;AAClB,IAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA,EAAY;AACjC,MAAA,QAAA,GAAW,KAAK,CAAC,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,OAAO,IAAA,CAAK,CAAC,MAAM,QAAA,IAAY,IAAA,CAAK,CAAC,CAAA,KAAM,IAAA,EAAM;AAC1D,MAAA,OAAA,GAAU,KAAK,CAAC,CAAA;AAChB,MAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA,EAAY;AACjC,QAAA,QAAA,GAAW,KAAK,CAAC,CAAA;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAA,MAAA,IAAW,IAAA,CAAK,CAAC,CAAA,YAAaA,OAAAA,EAAK;AACjC,IAAA,SAAA,GAAY,IAAA,CAAK,CAAC,CAAA,CAAE,QAAA,EAAS;AAC7B,IAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA,EAAY;AACjC,MAAA,QAAA,GAAW,KAAK,CAAC,CAAA;AAAA,IACnB,CAAA,MAAA,IAAW,OAAO,IAAA,CAAK,CAAC,MAAM,QAAA,IAAY,IAAA,CAAK,CAAC,CAAA,KAAM,IAAA,EAAM;AAC1D,MAAA,OAAA,GAAU,KAAK,CAAC,CAAA;AAChB,MAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA,EAAY;AACjC,QAAA,QAAA,GAAW,KAAK,CAAC,CAAA;AAAA,MACnB;AAAA,IACF;AAAA,EACF,CAAA,MAAA,IAAW,OAAO,IAAA,CAAK,CAAC,MAAM,QAAA,IAAY,IAAA,CAAK,CAAC,CAAA,KAAM,IAAA,EAAM;AAC1D,IAAA,OAAA,GAAU,KAAK,CAAC,CAAA;AAChB,IAAA,MAAM,QAAA,GAAY,QAAkC,QAAA,IAAY,OAAA;AAChE,IAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,QAAA,IAAY,OAAA,CAAQ,IAAA,IAAQ,WAAA;AACjD,IAAA,MAAM,OAAO,OAAA,CAAQ,IAAA,GAAO,CAAA,CAAA,EAAI,OAAA,CAAQ,IAAI,CAAA,CAAA,GAAK,EAAA;AACjD,IAAA,MAAM,IAAA,GAAO,QAAQ,IAAA,IAAQ,GAAA;AAC7B,IAAA,SAAA,GAAY,GAAG,QAAQ,CAAA,EAAA,EAAK,IAAI,CAAA,EAAG,IAAI,GAAG,IAAI,CAAA,CAAA;AAC9C,IAAA,IAAI,OAAO,IAAA,CAAK,CAAC,CAAA,KAAM,UAAA,EAAY;AACjC,MAAA,QAAA,GAAW,KAAK,CAAC,CAAA;AAAA,IACnB;AAAA,EACF,CAAA,MAAO;AACL,IAAA,SAAA,GAAY,EAAA;AAAA,EACd;AAEA,EAAA,OAAO,EAAE,SAAA,EAAW,OAAA,EAAS,QAAA,EAAS;AACxC;AAKA,SAAS,oBAAA,CACP,YACA,eAAA,EACqB;AACrB,EAAA,OAAO,SAAS,kBACX,IAAA,EACiB;AACpB,IAAA,IAAI;AACF,MAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,QAAA,EAAS,GAAI,iBAAiB,IAAI,CAAA;AAE9D,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAI,MAAM,8CAA8C,CAAA;AACxD,QAAA,KAAA,CAAM,YAAA,EAAA;AACN,QAAA,OAAQ,UAAA,CAAwB,KAAA;AAAA,UAC9B,eAAA,KAAoB,WAAWC,sBAAA,GAAQC,qBAAA;AAAA,UACvC;AAAA,SACF;AAAA,MACF;AAGA,MAAA,IACE,CAAC,aAAA;AAAA,QACC,SAAA;AAAA,QACA,MAAA,CAAO,QAAA;AAAA,QACP,MAAA,CAAO,OAAA;AAAA,QACP,MAAA,CAAO;AAAA,OACT,EACA;AACA,QAAI,KAAA,CAAM,wBAAwB,SAAS,CAAA;AAC3C,QAAA,KAAA,CAAM,YAAA,EAAA;AACN,QAAA,OAAQ,UAAA,CAAwB,KAAA;AAAA,UAC9B,eAAA,KAAoB,WAAWD,sBAAA,GAAQC,qBAAA;AAAA,UACvC;AAAA,SACF;AAAA,MACF;AAGA,MAAA,MAAM,WAAA,GAAc,IAAIF,OAAAA,CAAI,MAAA,CAAO,QAAQ,CAAA;AAG3C,MAAA,IAAI,YAAA;AACJ,MAAA,IAAI;AACF,QAAA,YAAA,GAAe,IAAIA,QAAI,SAAS,CAAA;AAAA,MAClC,CAAA,CAAA,MAAQ;AACN,QAAI,KAAA,CAAM,iCAAiC,SAAS,CAAA;AACpD,QAAA,KAAA,CAAM,YAAA,EAAA;AACN,QAAA,OAAQ,UAAA,CAAwB,KAAA;AAAA,UAC9B,eAAA,KAAoB,WAAWC,sBAAA,GAAQC,qBAAA;AAAA,UACvC;AAAA,SACF;AAAA,MACF;AAEA,MAAA,MAAM,eAAe,CAAA,EAAG,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK,aAAa,IAAI,CAAA,CAAA;AAGnE,MAAA,MAAM,cAAA,GAAsC;AAAA,QAC1C,GAAG,OAAA;AAAA,QACH,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,UAAU,WAAA,CAAY,QAAA;AAAA,QACtB,MAAM,WAAA,CAAY,IAAA,KAAS,WAAA,CAAY,QAAA,KAAa,WAAW,GAAA,GAAM,EAAA,CAAA;AAAA,QACrE,IAAA,EAAM,YAAA,CAAa,QAAA,GAAW,YAAA,CAAa,MAAA;AAAA,QAC3C,OAAA,EAAS;AAAA,UACP,GAAG,OAAA,CAAQ,OAAA;AAAA,UACX,aAAa,MAAA,CAAO,MAAA;AAAA,UACpB,iBAAA,EAAmB,YAAA;AAAA,UACnB,gBAAgB,MAAA,CAAO,WAAA;AAAA;AAAA,UAEvB,MAAM,YAAA,CAAa;AAAA;AACrB,OACF;AAGA,MAAA,IAAI,OAAO,SAAA,EAAW;AACpB,QAAC,cAAA,CAAe,OAAA,CAAmC,kBAAkB,CAAA,GACnE,MAAA,CAAO,SAAA;AAAA,MACX;AAGA,MAAA,IAAI,OAAO,OAAA,EAAS;AAClB,QAAA,cAAA,CAAe,UAAU,MAAA,CAAO,OAAA;AAAA,MAClC;AAEA,MAAI,KAAA,CAAM,cAAc,OAAA,CAAQ,MAAA,IAAU,OAAO,SAAA,EAAW,QAAA,EAAK,OAAO,QAAQ,CAAA;AAChF,MAAA,KAAA,CAAM,aAAA,EAAA;AAGN,MAAA,MAAM,QAAA,GAAW,IAAIF,OAAAA,CAAI,CAAA,EAAG,eAAe,QAAQ,CAAA,EAAA,EAAK,cAAA,CAAe,QAAQ,IAAI,cAAA,CAAe,IAAI,CAAA,EAAG,cAAA,CAAe,IAAI,CAAA,CAAE,CAAA;AAC9H,MAAA,OAAO,mBAAA,CAAqB,IAAA,CAAKE,qBAAA,EAAM,QAAA,EAAU,gBAAgB,QAAQ,CAAA;AAAA,IAC3E,SAAS,GAAA,EAAK;AACZ,MAAI,KAAA,CAAM,uCAAuC,GAAG,CAAA;AACpD,MAAA,KAAA,CAAM,WAAA,EAAA;AACN,MAAA,OAAQ,UAAA,CAAwB,KAAA;AAAA,QAC9B,eAAA,KAAoB,WAAWD,sBAAA,GAAQC,qBAAA;AAAA,QACvC;AAAA,OACF;AAAA,IACF;AAAA,EACF,CAAA;AACF;AAKA,SAAS,iBACP,cAAA,EACiB;AACjB,EAAA,OAAO,SAAS,cAAc,IAAA,EAAqC;AACjE,IAAA,MAAM,GAAA,GAAO,cAAA,CAA4B,GAAG,IAAI,CAAA;AAChD,IAAA,GAAA,CAAI,GAAA,EAAI;AACR,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AACF;AAKO,SAAS,uBAAuB,GAAA,EAA4B;AACjE,EAAA,IAAI,MAAA,EAAQ;AACV,IAAI,KAAK,kDAAkD,CAAA;AAC3D,IAAA;AAAA,EACF;AAEA,EAAA,MAAA,GAAS;AAAA,IACP,GAAG,GAAA;AAAA,IACH,QAAA,EAAU,SAAA;AAAA,IACV,WAAA,EAAa,IAAI,WAAA,IAAe;AAAA,GAClC;AAGA,EAAA,mBAAA,GAAsBA,qBAAA,CAAK,OAAA;AAC3B,EAAA,eAAA,GAAkBA,qBAAA,CAAK,GAAA;AACvB,EAAA,oBAAA,GAAuBD,sBAAA,CAAM,OAAA;AAC7B,EAAA,gBAAA,GAAmBA,sBAAA,CAAM,GAAA;AAGzB,EAAA,MAAM,kBAAA,GAAqB,oBAAA,CAAqB,mBAAA,EAAqB,OAAO,CAAA;AAC5E,EAAAC,qBAAA,CAAK,OAAA,GAAU,kBAAA;AACf,EAAAA,qBAAA,CAAK,GAAA,GAAM,iBAAiB,kBAAkB,CAAA;AAG9C,EAAA,MAAM,mBAAA,GAAsB,oBAAA;AAAA,IAC1B,oBAAA;AAAA,IACA;AAAA,GACF;AACA,EAAAD,sBAAA,CAAM,OAAA,GAAU,mBAAA;AAChB,EAAAA,sBAAA,CAAM,GAAA,GAAM,iBAAiB,mBAAmB,CAAA;AAGhD,EAAA,KAAA,CAAM,aAAA,GAAgB,CAAA;AACtB,EAAA,KAAA,CAAM,YAAA,GAAe,CAAA;AACrB,EAAA,KAAA,CAAM,WAAA,GAAc,CAAA;AACpB,EAAA,KAAA,CAAM,SAAA,uBAAgB,IAAA,EAAK;AAE3B,EAAA,MAAA,GAAS,IAAA;AACT,EAAI,MAAM,kCAAkC,CAAA;AAC9C;AAKO,SAAS,wBAAA,GAAiC;AAC/C,EAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,EAAA,IAAI,mBAAA,wBAA0B,OAAA,GAAU,mBAAA;AACxC,EAAA,IAAI,eAAA,wBAAsB,GAAA,GAAM,eAAA;AAChC,EAAA,IAAI,oBAAA,yBAA4B,OAAA,GAAU,oBAAA;AAC1C,EAAA,IAAI,gBAAA,yBAAwB,GAAA,GAAM,gBAAA;AAElC,EAAA,mBAAA,GAAsB,IAAA;AACtB,EAAA,eAAA,GAAkB,IAAA;AAClB,EAAA,oBAAA,GAAuB,IAAA;AACvB,EAAA,gBAAA,GAAmB,IAAA;AAEnB,EAAA,MAAA,GAAS,KAAA;AACT,EAAI,MAAM,gCAAgC,CAAA;AAC5C;AAEO,SAAS,uBAAA,GAAmC;AACjD,EAAA,OAAO,MAAA;AACT;AAEO,SAAS,YAAA,GAA6B;AAC3C,EAAA,OAAO,EAAE,GAAG,KAAA,EAAM;AACpB;;;AClRA,IAAME,UAAAA,GAAY,OAAA,CAAQ,GAAA,CAAI,gBAAA,IAAoB,uBAAA;AAElD,IAAI,aAAA,GAAgD,IAAA;AACpD,IAAIC,OAAAA,GAAS,KAAA;AACb,IAAIC,OAAAA;AAKJ,IAAMC,MAAAA,GAAsB;AAAA,EAC1B,aAAA,EAAe,CAAA;AAAA,EACf,YAAA,EAAc,CAAA;AAAA,EACd,WAAA,EAAa,CAAA;AAAA,EACb,SAAA,sBAAe,IAAA;AACjB,CAAA;AAKO,SAAS,wBAAwB,GAAA,EAA4B;AAClE,EAAA,IAAIF,OAAAA,EAAQ;AACV,IAAI,KAAK,qCAAqC,CAAA;AAC9C,IAAA;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,UAAA,CAAW,KAAA,KAAU,UAAA,EAAY;AAC1C,IAAI,MAAM,4DAA4D,CAAA;AACtE,IAAA;AAAA,EACF;AAEA,EAAAC,OAAAA,GAAS;AAAA,IACP,GAAG,GAAA;AAAA,IACH,QAAA,EAAUF,UAAAA;AAAA,IACV,WAAA,EAAa,IAAI,WAAA,IAAe;AAAA,GAClC;AAEA,EAAA,aAAA,GAAgB,UAAA,CAAW,KAAA;AAE3B,EAAA,UAAA,CAAW,KAAA,GAAQ,eAAe,YAAA,CAChC,KAAA,EACAI,KAAAA,EACmB;AACnB,IAAA,IAAI;AAEF,MAAA,IAAI,SAAA;AACJ,MAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,QAAA,SAAA,GAAY,KAAA;AAAA,MACd,CAAA,MAAA,IAAW,iBAAiB,GAAA,EAAK;AAC/B,QAAA,SAAA,GAAY,MAAM,QAAA,EAAS;AAAA,MAC7B,CAAA,MAAA,IAAW,iBAAiB,OAAA,EAAS;AACnC,QAAA,SAAA,GAAY,KAAA,CAAM,GAAA;AAAA,MACpB,CAAA,MAAO;AACL,QAAA,SAAA,GAAY,OAAO,KAAK,CAAA;AAAA,MAC1B;AAGA,MAAA,IACE,CAAC,aAAA;AAAA,QACC,SAAA;AAAA,QACAF,OAAAA,CAAO,QAAA;AAAA,QACPA,OAAAA,CAAO,OAAA;AAAA,QACPA,OAAAA,CAAO;AAAA,OACT,EACA;AACA,QAAI,KAAA,CAAM,8BAA8B,SAAS,CAAA;AACjD,QAAAC,MAAAA,CAAM,YAAA,EAAA;AACN,QAAA,OAAO,aAAA,CAAe,OAAOC,KAAI,CAAA;AAAA,MACnC;AAGA,MAAA,IAAI,YAAA;AACJ,MAAA,IAAI;AACF,QAAA,YAAA,GAAe,IAAI,IAAI,SAAS,CAAA;AAAA,MAClC,CAAA,CAAA,MAAQ;AACN,QAAI,KAAA,CAAM,wCAAwC,SAAS,CAAA;AAC3D,QAAAD,MAAAA,CAAM,YAAA,EAAA;AACN,QAAA,OAAO,aAAA,CAAe,OAAOC,KAAI,CAAA;AAAA,MACnC;AAEA,MAAA,MAAM,eAAe,CAAA,EAAG,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK,aAAa,IAAI,CAAA,CAAA;AACnE,MAAA,MAAM,SAAA,GAAY,YAAA,CAAa,QAAA,GAAW,YAAA,CAAa,MAAA;AACvD,MAAA,MAAM,UAAA,GAAa,CAAA,EAAGF,OAAAA,CAAO,QAAQ,GAAG,SAAS,CAAA,CAAA;AAGjD,MAAA,MAAM,UAAU,IAAI,OAAA,CAAQE,KAAAA,EAAM,OAAA,IAAW,EAAE,CAAA;AAG/C,MAAA,IAAI,iBAAiB,OAAA,EAAS;AAC5B,QAAA,KAAA,CAAM,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AACpC,UAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,GAAG,CAAA,EAAG;AACrB,YAAA,OAAA,CAAQ,GAAA,CAAI,KAAK,KAAK,CAAA;AAAA,UACxB;AAAA,QACF,CAAC,CAAA;AAAA,MACH;AAGA,MAAA,OAAA,CAAQ,GAAA,CAAI,WAAA,EAAaF,OAAAA,CAAO,MAAM,CAAA;AACtC,MAAA,OAAA,CAAQ,GAAA,CAAI,mBAAmB,YAAY,CAAA;AAC3C,MAAA,OAAA,CAAQ,GAAA,CAAI,cAAA,EAAgBA,OAAAA,CAAO,WAAW,CAAA;AAC9C,MAAA,OAAA,CAAQ,GAAA,CAAI,MAAA,EAAQ,YAAA,CAAa,IAAI,CAAA;AAErC,MAAA,IAAIA,QAAO,SAAA,EAAW;AACpB,QAAA,OAAA,CAAQ,GAAA,CAAI,kBAAA,EAAoBA,OAAAA,CAAO,SAAS,CAAA;AAAA,MAClD;AAGA,MAAA,MAAM,WAAA,GAA2B;AAAA,QAC/B,GAAGE,KAAAA;AAAA,QACH;AAAA,OACF;AAGA,MAAA,IAAI,iBAAiB,OAAA,EAAS;AAC5B,QAAA,WAAA,CAAY,MAAA,GAAS,WAAA,CAAY,MAAA,IAAU,KAAA,CAAM,MAAA;AACjD,QAAA,IAAI,CAAC,WAAA,CAAY,IAAA,IAAQ,KAAA,CAAM,IAAA,EAAM;AACnC,UAAA,WAAA,CAAY,OAAO,KAAA,CAAM,IAAA;AAAA,QAC3B;AAAA,MACF;AAEA,MAAI,KAAA;AAAA,QACF,kBAAA;AAAA,QACA,YAAY,MAAA,IAAU,KAAA;AAAA,QACtB,SAAA;AAAA,QACA,QAAA;AAAA,QACAF,OAAAA,CAAO;AAAA,OACT;AACA,MAAAC,MAAAA,CAAM,aAAA,EAAA;AAEN,MAAA,OAAO,aAAA,CAAe,YAAY,WAAW,CAAA;AAAA,IAC/C,SAAS,GAAA,EAAK;AACZ,MAAI,KAAA,CAAM,6CAA6C,GAAG,CAAA;AAC1D,MAAAA,MAAAA,CAAM,WAAA,EAAA;AACN,MAAA,OAAO,aAAA,CAAe,OAAOC,KAAI,CAAA;AAAA,IACnC;AAAA,EACF,CAAA;AAGA,EAAAD,OAAM,aAAA,GAAgB,CAAA;AACtB,EAAAA,OAAM,YAAA,GAAe,CAAA;AACrB,EAAAA,OAAM,WAAA,GAAc,CAAA;AACpB,EAAAA,MAAAA,CAAM,SAAA,mBAAY,IAAI,IAAA,EAAK;AAE3B,EAAAF,OAAAA,GAAS,IAAA;AACT,EAAI,MAAM,6BAA6B,CAAA;AACzC;AAKO,SAAS,yBAAA,GAAkC;AAChD,EAAA,IAAI,CAACA,OAAAA,IAAU,CAAC,aAAA,EAAe;AAE/B,EAAA,UAAA,CAAW,KAAA,GAAQ,aAAA;AACnB,EAAA,aAAA,GAAgB,IAAA;AAChB,EAAAA,OAAAA,GAAS,KAAA;AACT,EAAI,MAAM,2BAA2B,CAAA;AACvC;AAEO,SAAS,wBAAA,GAAoC;AAClD,EAAA,OAAOA,OAAAA;AACT;AAEO,SAAS,aAAA,GAA8B;AAC5C,EAAA,OAAO,EAAE,GAAGE,MAAAA,EAAM;AACpB;;;AC5IA,IAAI,WAAA,GAAc,KAAA;AAkBlB,SAAS,KAAK,cAAA,EAA6D;AAEzE,EAAA,MAAMD,UACJ,OAAO,cAAA,KAAmB,WAAW,EAAE,MAAA,EAAQ,gBAAe,GAAI,cAAA;AAEpE,EAAA,IAAI,WAAA,EAAa;AACf,IAAI,KAAK,0EAAqE,CAAA;AAC9E,IAAA,IAAA,EAAK;AAAA,EACP;AAGA,EAAA,IAAI,CAACA,QAAO,MAAA,EAAQ;AAClB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAIA,QAAO,QAAA,EAAU;AACnB,IAAI,KAAK,kDAAkD,CAAA;AAC3D,IAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAS;AAAA,EACpC;AAGA,EAAA,IAAIA,QAAO,KAAA,EAAO;AAChB,IAAA,QAAA,CAAS,IAAI,CAAA;AAAA,EACf;AAGA,EAAAA,QAAO,WAAA,GACLA,OAAAA,CAAO,WAAA,IAAe,OAAA,CAAQ,IAAI,kBAAA,IAAsB,aAAA;AAE1D,EAAI,IAAA,CAAK,CAAA,wBAAA,EAAsBA,OAAAA,CAAO,WAAW,CAAA,CAAE,CAAA;AAGnD,EAAA,sBAAA,CAAuBA,OAAM,CAAA;AAC7B,EAAA,uBAAA,CAAwBA,OAAM,CAAA;AAE9B,EAAA,WAAA,GAAc,IAAA;AAEd,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAS;AACpC;AAKA,SAAS,IAAA,GAAa;AACpB,EAAA,IAAI,CAAC,WAAA,EAAa;AAElB,EAAA,wBAAA,EAAyB;AACzB,EAAA,yBAAA,EAA0B;AAE1B,EAAA,WAAA,GAAc,KAAA;AACd,EAAI,KAAK,yCAAoC,CAAA;AAC/C;AAKA,SAAS,QAAA,GAAoB;AAC3B,EAAA,OAAO,uBAAA,MAA6B,wBAAA,EAAyB;AAC/D;AAKA,SAAS,QAAA,GAAyB;AAChC,EAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,EAAA,MAAM,aAAa,aAAA,EAAc;AAEjC,EAAA,OAAO;AAAA,IACL,aAAA,EAAe,SAAA,CAAU,aAAA,GAAgB,UAAA,CAAW,aAAA;AAAA,IACpD,YAAA,EAAc,SAAA,CAAU,YAAA,GAAe,UAAA,CAAW,YAAA;AAAA,IAClD,WAAA,EAAa,SAAA,CAAU,WAAA,GAAc,UAAA,CAAW,WAAA;AAAA,IAChD,WAAW,SAAA,CAAU,SAAA,GAAY,WAAW,SAAA,GACxC,SAAA,CAAU,YACV,UAAA,CAAW;AAAA,GACjB;AACF;AAKO,IAAM,SAAA,GAAY;AAAA,EACvB,IAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF","file":"index.js","sourcesContent":["/**\r\n * ReplayAPI SDK — URL matching utilities\r\n */\r\n\r\n/**\r\n * Check if a URL matches any of the given patterns.\r\n * Patterns can be strings (substring match) or RegExp.\r\n */\r\nexport function matchesPatterns(\r\n url: string,\r\n patterns: Array<string | RegExp>\r\n): boolean {\r\n return patterns.some((pattern) => {\r\n if (typeof pattern === \"string\") {\r\n return url.includes(pattern);\r\n }\r\n return pattern.test(url);\r\n });\r\n}\r\n\r\n/**\r\n * Determine if a request URL should be captured based on include/exclude filters.\r\n */\r\nexport function shouldCapture(\r\n url: string,\r\n proxyUrl: string,\r\n include?: Array<string | RegExp>,\r\n exclude?: Array<string | RegExp>\r\n): boolean {\r\n // Never capture requests to the proxy itself\r\n if (url.startsWith(proxyUrl)) {\r\n return false;\r\n }\r\n\r\n // Never capture requests to ReplayAPI internal paths\r\n if (url.includes(\"/__replay/\")) {\r\n return false;\r\n }\r\n\r\n // If include patterns are set, URL must match at least one\r\n if (include && include.length > 0) {\r\n if (!matchesPatterns(url, include)) {\r\n return false;\r\n }\r\n }\r\n\r\n // If exclude patterns are set, URL must not match any\r\n if (exclude && exclude.length > 0) {\r\n if (matchesPatterns(url, exclude)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * ReplayAPI SDK — Simple logger\r\n */\r\n\r\nlet debugEnabled = false;\r\n\r\nexport function setDebug(enabled: boolean): void {\r\n debugEnabled = enabled;\r\n}\r\n\r\nexport function debug(...args: unknown[]): void {\r\n if (debugEnabled) {\r\n console.log(\"[replayapi]\", ...args);\r\n }\r\n}\r\n\r\nexport function info(...args: unknown[]): void {\r\n console.log(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function warn(...args: unknown[]): void {\r\n console.warn(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function error(...args: unknown[]): void {\r\n console.error(\"[replayapi]\", ...args);\r\n}\r\n","/**\r\n * ReplayAPI SDK — HTTP/HTTPS interceptor\r\n *\r\n * Monkey-patches Node.js http.request and https.request to redirect\r\n * outgoing requests through the ReplayAPI proxy. The proxy captures\r\n * the traffic and forwards it to the original target.\r\n *\r\n * How it works:\r\n * 1. Original request: GET https://api.example.com/users\r\n * 2. SDK rewrites to: GET http://proxy:8080/users\r\n * with headers:\r\n * X-Api-Key: rp_...\r\n * X-Replay-Target: https://api.example.com\r\n * X-Replay-Env: staging\r\n * 3. Proxy captures, forwards to target, returns response transparently\r\n */\r\n\r\nimport http from \"node:http\";\r\nimport https from \"node:https\";\r\nimport { URL } from \"node:url\";\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\n// Store original implementations\r\nlet originalHttpRequest: typeof http.request | null = null;\r\nlet originalHttpGet: typeof http.get | null = null;\r\nlet originalHttpsRequest: typeof https.request | null = null;\r\nlet originalHttpsGet: typeof https.get | null = null;\r\n\r\nconst PROXY_URL = process.env.REPLAY_PROXY_URL || \"http://localhost:8080\";\r\n\r\n// Track state\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Parse the various argument formats that http.request accepts:\r\n * - (url: string, options?, callback?)\r\n * - (url: URL, options?, callback?)\r\n * - (options, callback?)\r\n */\r\nfunction parseRequestArgs(\r\n args: unknown[]\r\n): {\r\n targetUrl: string;\r\n options: http.RequestOptions;\r\n callback?: (res: http.IncomingMessage) => void;\r\n} {\r\n let targetUrl: string;\r\n let options: http.RequestOptions = {};\r\n let callback: ((res: http.IncomingMessage) => void) | undefined;\r\n\r\n if (typeof args[0] === \"string\") {\r\n targetUrl = args[0];\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (args[0] instanceof URL) {\r\n targetUrl = args[0].toString();\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\r\n options = args[0] as http.RequestOptions;\r\n const protocol = (options as { protocol?: string }).protocol || \"http:\";\r\n const host = options.hostname || options.host || \"localhost\";\r\n const port = options.port ? `:${options.port}` : \"\";\r\n const path = options.path || \"/\";\r\n targetUrl = `${protocol}//${host}${port}${path}`;\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n }\r\n } else {\r\n targetUrl = \"\";\r\n }\r\n\r\n return { targetUrl, options, callback };\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.request / https.request\r\n */\r\nfunction createProxiedRequest(\r\n originalFn: typeof http.request,\r\n defaultProtocol: \"http:\" | \"https:\"\r\n): typeof http.request {\r\n return function proxiedRequest(\r\n ...args: unknown[]\r\n ): http.ClientRequest {\r\n try {\r\n const { targetUrl, options, callback } = parseRequestArgs(args);\r\n\r\n if (!targetUrl) {\r\n log.debug(\"could not parse request URL, passing through\");\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Parse the proxy URL\r\n const proxyParsed = new URL(config.proxyUrl);\r\n\r\n // Parse the target URL to extract origin and path\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n\r\n // Build proxied options: send to proxy, with X-Replay-Target header\r\n const proxiedOptions: http.RequestOptions = {\r\n ...options,\r\n protocol: proxyParsed.protocol,\r\n hostname: proxyParsed.hostname,\r\n port: proxyParsed.port || (proxyParsed.protocol === \"https:\" ? 443 : 80),\r\n path: parsedTarget.pathname + parsedTarget.search,\r\n headers: {\r\n ...options.headers,\r\n \"X-Api-Key\": config.apiKey,\r\n \"X-Replay-Target\": targetOrigin,\r\n \"X-Replay-Env\": config.environment,\r\n // Preserve the original Host header\r\n Host: parsedTarget.host,\r\n },\r\n };\r\n\r\n // Add session ID if configured\r\n if (config.sessionId) {\r\n (proxiedOptions.headers as Record<string, string>)[\"X-Replay-Session\"] =\r\n config.sessionId;\r\n }\r\n\r\n // Set timeout if configured\r\n if (config.timeout) {\r\n proxiedOptions.timeout = config.timeout;\r\n }\r\n\r\n log.debug(\"capturing:\", options.method || \"GET\", targetUrl, \"→\", config.proxyUrl);\r\n stats.totalCaptured++;\r\n\r\n // Use http.request (not https) since we're talking to the proxy over HTTP\r\n const proxyUrl = new URL(`${proxiedOptions.protocol}//${proxiedOptions.hostname}:${proxiedOptions.port}${proxiedOptions.path}`);\r\n return originalHttpRequest!.call(http, proxyUrl, proxiedOptions, callback);\r\n } catch (err) {\r\n log.error(\"interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n } as typeof http.request;\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.get / https.get\r\n */\r\nfunction createProxiedGet(\r\n proxiedRequest: typeof http.request\r\n): typeof http.get {\r\n return function proxiedGet(...args: unknown[]): http.ClientRequest {\r\n const req = (proxiedRequest as Function)(...args) as http.ClientRequest;\r\n req.end();\r\n return req;\r\n } as typeof http.get;\r\n}\r\n\r\n/**\r\n * Install the HTTP/HTTPS interceptors\r\n */\r\nexport function installHttpInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"interceptor already installed, call stop() first\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n // Save originals\r\n originalHttpRequest = http.request;\r\n originalHttpGet = http.get;\r\n originalHttpsRequest = https.request;\r\n originalHttpsGet = https.get;\r\n\r\n // Patch http\r\n const proxiedHttpRequest = createProxiedRequest(originalHttpRequest, \"http:\");\r\n http.request = proxiedHttpRequest;\r\n http.get = createProxiedGet(proxiedHttpRequest);\r\n\r\n // Patch https\r\n const proxiedHttpsRequest = createProxiedRequest(\r\n originalHttpsRequest,\r\n \"https:\"\r\n );\r\n https.request = proxiedHttpsRequest;\r\n https.get = createProxiedGet(proxiedHttpsRequest);\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"http/https interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the HTTP/HTTPS interceptors\r\n */\r\nexport function uninstallHttpInterceptor(): void {\r\n if (!active) return;\r\n\r\n if (originalHttpRequest) http.request = originalHttpRequest;\r\n if (originalHttpGet) http.get = originalHttpGet;\r\n if (originalHttpsRequest) https.request = originalHttpsRequest;\r\n if (originalHttpsGet) https.get = originalHttpsGet;\r\n\r\n originalHttpRequest = null;\r\n originalHttpGet = null;\r\n originalHttpsRequest = null;\r\n originalHttpsGet = null;\r\n\r\n active = false;\r\n log.debug(\"http/https interceptor removed\");\r\n}\r\n\r\nexport function isHttpInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getHttpStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * ReplayAPI SDK — Global fetch() interceptor\r\n *\r\n * Patches globalThis.fetch to route requests through the ReplayAPI proxy.\r\n * Works with Node.js 18+ native fetch and any polyfills that set globalThis.fetch.\r\n */\r\n\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nconst PROXY_URL = process.env.REPLAY_PROXY_URL || \"http://localhost:8080\";\r\n\r\nlet originalFetch: typeof globalThis.fetch | null = null;\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Install the fetch interceptor\r\n */\r\nexport function installFetchInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"fetch interceptor already installed\");\r\n return;\r\n }\r\n\r\n // Only patch if fetch exists (Node.js 18+)\r\n if (typeof globalThis.fetch !== \"function\") {\r\n log.debug(\"globalThis.fetch not available, skipping fetch interceptor\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n originalFetch = globalThis.fetch;\r\n\r\n globalThis.fetch = async function proxiedFetch(\r\n input: string | URL | Request,\r\n init?: RequestInit\r\n ): Promise<Response> {\r\n try {\r\n // Resolve the target URL\r\n let targetUrl: string;\r\n if (typeof input === \"string\") {\r\n targetUrl = input;\r\n } else if (input instanceof URL) {\r\n targetUrl = input.toString();\r\n } else if (input instanceof Request) {\r\n targetUrl = input.url;\r\n } else {\r\n targetUrl = String(input);\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"fetch skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n // Parse target URL\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"fetch: invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n const proxyPath = parsedTarget.pathname + parsedTarget.search;\r\n const proxiedUrl = `${config.proxyUrl}${proxyPath}`;\r\n\r\n // Build headers\r\n const headers = new Headers(init?.headers || {});\r\n\r\n // If input is a Request, merge its headers too\r\n if (input instanceof Request) {\r\n input.headers.forEach((value, key) => {\r\n if (!headers.has(key)) {\r\n headers.set(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Add ReplayAPI headers\r\n headers.set(\"X-Api-Key\", config.apiKey);\r\n headers.set(\"X-Replay-Target\", targetOrigin);\r\n headers.set(\"X-Replay-Env\", config.environment);\r\n headers.set(\"Host\", parsedTarget.host);\r\n\r\n if (config.sessionId) {\r\n headers.set(\"X-Replay-Session\", config.sessionId);\r\n }\r\n\r\n // Build proxied init\r\n const proxiedInit: RequestInit = {\r\n ...init,\r\n headers,\r\n };\r\n\r\n // If input is a Request, preserve method and body\r\n if (input instanceof Request) {\r\n proxiedInit.method = proxiedInit.method || input.method;\r\n if (!proxiedInit.body && input.body) {\r\n proxiedInit.body = input.body;\r\n }\r\n }\r\n\r\n log.debug(\r\n \"fetch capturing:\",\r\n proxiedInit.method || \"GET\",\r\n targetUrl,\r\n \"→\",\r\n config.proxyUrl\r\n );\r\n stats.totalCaptured++;\r\n\r\n return originalFetch!(proxiedUrl, proxiedInit);\r\n } catch (err) {\r\n log.error(\"fetch interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return originalFetch!(input, init);\r\n }\r\n };\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"fetch interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the fetch interceptor\r\n */\r\nexport function uninstallFetchInterceptor(): void {\r\n if (!active || !originalFetch) return;\r\n\r\n globalThis.fetch = originalFetch;\r\n originalFetch = null;\r\n active = false;\r\n log.debug(\"fetch interceptor removed\");\r\n}\r\n\r\nexport function isFetchInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getFetchStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * @replayapi/node — ReplayAPI SDK for Node.js\r\n *\r\n * Automatically captures outgoing HTTP traffic and routes it through\r\n * the ReplayAPI proxy for recording, analysis, and replay testing.\r\n *\r\n * @example\r\n * ```ts\r\n * import { replayApi } from '@replayapi/node'\r\n *\r\n * // Simplest — just pass your API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: 'rp_your_api_key', environment: 'staging' })\r\n *\r\n * // All outgoing HTTP/fetch calls are now captured automatically\r\n * ```\r\n */\r\n\r\nimport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\nimport {\r\n installHttpInterceptor,\r\n uninstallHttpInterceptor,\r\n isHttpInterceptorActive,\r\n getHttpStats,\r\n} from \"./interceptor-http.js\";\r\nimport {\r\n installFetchInterceptor,\r\n uninstallFetchInterceptor,\r\n isFetchInterceptorActive,\r\n getFetchStats,\r\n} from \"./interceptor-fetch.js\";\r\nimport { setDebug } from \"./logger.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nlet initialized = false;\r\n\r\n/**\r\n * Initialize the ReplayAPI SDK.\r\n *\r\n * Call this once at application startup, before any outgoing HTTP requests.\r\n * The SDK will automatically intercept `http.request`, `https.request`,\r\n * and `fetch` to route traffic through the ReplayAPI proxy.\r\n *\r\n * @example\r\n * ```ts\r\n * // Just an API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: process.env.REPLAY_API_KEY!, environment: 'staging' })\r\n * ```\r\n */\r\nfunction init(configOrApiKey: ReplayApiConfig | string): ReplayApiInstance {\r\n // Accept a plain string as shorthand for { apiKey: string }\r\n const config: ReplayApiConfig =\r\n typeof configOrApiKey === \"string\" ? { apiKey: configOrApiKey } : configOrApiKey;\r\n\r\n if (initialized) {\r\n log.warn(\"replayApi.init() called multiple times — stopping previous instance\");\r\n stop();\r\n }\r\n\r\n // Validate config\r\n if (!config.apiKey) {\r\n throw new Error(\r\n \"[@replayapi/node] apiKey is required. Get one from your ReplayAPI dashboard.\"\r\n );\r\n }\r\n\r\n if (config.disabled) {\r\n log.info(\"SDK disabled via config, skipping initialization\");\r\n return { stop, isActive, getStats };\r\n }\r\n\r\n // Enable debug logging if requested\r\n if (config.debug) {\r\n setDebug(true);\r\n }\r\n\r\n // Resolve environment with env var fallback\r\n config.environment =\r\n config.environment || process.env.REPLAY_ENVIRONMENT || \"development\";\r\n\r\n log.info(`initialized — env: ${config.environment}`);\r\n\r\n // Install interceptors\r\n installHttpInterceptor(config);\r\n installFetchInterceptor(config);\r\n\r\n initialized = true;\r\n\r\n return { stop, isActive, getStats };\r\n}\r\n\r\n/**\r\n * Stop the SDK and restore original HTTP/fetch behavior.\r\n */\r\nfunction stop(): void {\r\n if (!initialized) return;\r\n\r\n uninstallHttpInterceptor();\r\n uninstallFetchInterceptor();\r\n\r\n initialized = false;\r\n log.info(\"stopped — all interceptors removed\");\r\n}\r\n\r\n/**\r\n * Check if the SDK is currently intercepting traffic.\r\n */\r\nfunction isActive(): boolean {\r\n return isHttpInterceptorActive() || isFetchInterceptorActive();\r\n}\r\n\r\n/**\r\n * Get combined capture statistics from all interceptors.\r\n */\r\nfunction getStats(): CaptureStats {\r\n const httpStats = getHttpStats();\r\n const fetchStats = getFetchStats();\r\n\r\n return {\r\n totalCaptured: httpStats.totalCaptured + fetchStats.totalCaptured,\r\n totalSkipped: httpStats.totalSkipped + fetchStats.totalSkipped,\r\n totalErrors: httpStats.totalErrors + fetchStats.totalErrors,\r\n startedAt: httpStats.startedAt < fetchStats.startedAt\r\n ? httpStats.startedAt\r\n : fetchStats.startedAt,\r\n };\r\n}\r\n\r\n/**\r\n * The main ReplayAPI SDK instance.\r\n */\r\nexport const replayApi = {\r\n init,\r\n stop,\r\n isActive,\r\n getStats,\r\n};\r\n\r\n// Named exports for flexibility\r\nexport { init, stop, isActive, getStats };\r\n\r\n// Re-export types\r\nexport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\n"]}
package/dist/index.mjs CHANGED
@@ -58,7 +58,7 @@ var originalHttpRequest = null;
58
58
  var originalHttpGet = null;
59
59
  var originalHttpsRequest = null;
60
60
  var originalHttpsGet = null;
61
- var PROXY_URL = "http://localhost:8080";
61
+ var PROXY_URL = process.env.REPLAY_PROXY_URL || "http://localhost:8080";
62
62
  var active = false;
63
63
  var config;
64
64
  var stats = {
@@ -237,7 +237,7 @@ function getHttpStats() {
237
237
  }
238
238
 
239
239
  // src/interceptor-fetch.ts
240
- var PROXY_URL2 = "http://localhost:8080";
240
+ var PROXY_URL2 = process.env.REPLAY_PROXY_URL || "http://localhost:8080";
241
241
  var originalFetch = null;
242
242
  var active2 = false;
243
243
  var config2;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/matcher.ts","../src/logger.ts","../src/interceptor-http.ts","../src/interceptor-fetch.ts","../src/index.ts"],"names":["URL","PROXY_URL","active","config","stats","init"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * ReplayAPI SDK — URL matching utilities\r\n */\r\n\r\n/**\r\n * Check if a URL matches any of the given patterns.\r\n * Patterns can be strings (substring match) or RegExp.\r\n */\r\nexport function matchesPatterns(\r\n url: string,\r\n patterns: Array<string | RegExp>\r\n): boolean {\r\n return patterns.some((pattern) => {\r\n if (typeof pattern === \"string\") {\r\n return url.includes(pattern);\r\n }\r\n return pattern.test(url);\r\n });\r\n}\r\n\r\n/**\r\n * Determine if a request URL should be captured based on include/exclude filters.\r\n */\r\nexport function shouldCapture(\r\n url: string,\r\n proxyUrl: string,\r\n include?: Array<string | RegExp>,\r\n exclude?: Array<string | RegExp>\r\n): boolean {\r\n // Never capture requests to the proxy itself\r\n if (url.startsWith(proxyUrl)) {\r\n return false;\r\n }\r\n\r\n // Never capture requests to ReplayAPI internal paths\r\n if (url.includes(\"/__replay/\")) {\r\n return false;\r\n }\r\n\r\n // If include patterns are set, URL must match at least one\r\n if (include && include.length > 0) {\r\n if (!matchesPatterns(url, include)) {\r\n return false;\r\n }\r\n }\r\n\r\n // If exclude patterns are set, URL must not match any\r\n if (exclude && exclude.length > 0) {\r\n if (matchesPatterns(url, exclude)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * ReplayAPI SDK — Simple logger\r\n */\r\n\r\nlet debugEnabled = false;\r\n\r\nexport function setDebug(enabled: boolean): void {\r\n debugEnabled = enabled;\r\n}\r\n\r\nexport function debug(...args: unknown[]): void {\r\n if (debugEnabled) {\r\n console.log(\"[replayapi]\", ...args);\r\n }\r\n}\r\n\r\nexport function info(...args: unknown[]): void {\r\n console.log(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function warn(...args: unknown[]): void {\r\n console.warn(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function error(...args: unknown[]): void {\r\n console.error(\"[replayapi]\", ...args);\r\n}\r\n","/**\r\n * ReplayAPI SDK — HTTP/HTTPS interceptor\r\n *\r\n * Monkey-patches Node.js http.request and https.request to redirect\r\n * outgoing requests through the ReplayAPI proxy. The proxy captures\r\n * the traffic and forwards it to the original target.\r\n *\r\n * How it works:\r\n * 1. Original request: GET https://api.example.com/users\r\n * 2. SDK rewrites to: GET http://proxy:8080/users\r\n * with headers:\r\n * X-Api-Key: rp_...\r\n * X-Replay-Target: https://api.example.com\r\n * X-Replay-Env: staging\r\n * 3. Proxy captures, forwards to target, returns response transparently\r\n */\r\n\r\nimport http from \"node:http\";\r\nimport https from \"node:https\";\r\nimport { URL } from \"node:url\";\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\n// Store original implementations\r\nlet originalHttpRequest: typeof http.request | null = null;\r\nlet originalHttpGet: typeof http.get | null = null;\r\nlet originalHttpsRequest: typeof https.request | null = null;\r\nlet originalHttpsGet: typeof https.get | null = null;\r\n\r\nconst PROXY_URL = \"http://localhost:8080\";\r\n\r\n// Track state\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Parse the various argument formats that http.request accepts:\r\n * - (url: string, options?, callback?)\r\n * - (url: URL, options?, callback?)\r\n * - (options, callback?)\r\n */\r\nfunction parseRequestArgs(\r\n args: unknown[]\r\n): {\r\n targetUrl: string;\r\n options: http.RequestOptions;\r\n callback?: (res: http.IncomingMessage) => void;\r\n} {\r\n let targetUrl: string;\r\n let options: http.RequestOptions = {};\r\n let callback: ((res: http.IncomingMessage) => void) | undefined;\r\n\r\n if (typeof args[0] === \"string\") {\r\n targetUrl = args[0];\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (args[0] instanceof URL) {\r\n targetUrl = args[0].toString();\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\r\n options = args[0] as http.RequestOptions;\r\n const protocol = (options as { protocol?: string }).protocol || \"http:\";\r\n const host = options.hostname || options.host || \"localhost\";\r\n const port = options.port ? `:${options.port}` : \"\";\r\n const path = options.path || \"/\";\r\n targetUrl = `${protocol}//${host}${port}${path}`;\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n }\r\n } else {\r\n targetUrl = \"\";\r\n }\r\n\r\n return { targetUrl, options, callback };\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.request / https.request\r\n */\r\nfunction createProxiedRequest(\r\n originalFn: typeof http.request,\r\n defaultProtocol: \"http:\" | \"https:\"\r\n): typeof http.request {\r\n return function proxiedRequest(\r\n ...args: unknown[]\r\n ): http.ClientRequest {\r\n try {\r\n const { targetUrl, options, callback } = parseRequestArgs(args);\r\n\r\n if (!targetUrl) {\r\n log.debug(\"could not parse request URL, passing through\");\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Parse the proxy URL\r\n const proxyParsed = new URL(config.proxyUrl);\r\n\r\n // Parse the target URL to extract origin and path\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n\r\n // Build proxied options: send to proxy, with X-Replay-Target header\r\n const proxiedOptions: http.RequestOptions = {\r\n ...options,\r\n protocol: proxyParsed.protocol,\r\n hostname: proxyParsed.hostname,\r\n port: proxyParsed.port || (proxyParsed.protocol === \"https:\" ? 443 : 80),\r\n path: parsedTarget.pathname + parsedTarget.search,\r\n headers: {\r\n ...options.headers,\r\n \"X-Api-Key\": config.apiKey,\r\n \"X-Replay-Target\": targetOrigin,\r\n \"X-Replay-Env\": config.environment,\r\n // Preserve the original Host header\r\n Host: parsedTarget.host,\r\n },\r\n };\r\n\r\n // Add session ID if configured\r\n if (config.sessionId) {\r\n (proxiedOptions.headers as Record<string, string>)[\"X-Replay-Session\"] =\r\n config.sessionId;\r\n }\r\n\r\n // Set timeout if configured\r\n if (config.timeout) {\r\n proxiedOptions.timeout = config.timeout;\r\n }\r\n\r\n log.debug(\"capturing:\", options.method || \"GET\", targetUrl, \"→\", config.proxyUrl);\r\n stats.totalCaptured++;\r\n\r\n // Use http.request (not https) since we're talking to the proxy over HTTP\r\n const proxyUrl = new URL(`${proxiedOptions.protocol}//${proxiedOptions.hostname}:${proxiedOptions.port}${proxiedOptions.path}`);\r\n return originalHttpRequest!.call(http, proxyUrl, proxiedOptions, callback);\r\n } catch (err) {\r\n log.error(\"interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n } as typeof http.request;\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.get / https.get\r\n */\r\nfunction createProxiedGet(\r\n proxiedRequest: typeof http.request\r\n): typeof http.get {\r\n return function proxiedGet(...args: unknown[]): http.ClientRequest {\r\n const req = (proxiedRequest as Function)(...args) as http.ClientRequest;\r\n req.end();\r\n return req;\r\n } as typeof http.get;\r\n}\r\n\r\n/**\r\n * Install the HTTP/HTTPS interceptors\r\n */\r\nexport function installHttpInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"interceptor already installed, call stop() first\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n // Save originals\r\n originalHttpRequest = http.request;\r\n originalHttpGet = http.get;\r\n originalHttpsRequest = https.request;\r\n originalHttpsGet = https.get;\r\n\r\n // Patch http\r\n const proxiedHttpRequest = createProxiedRequest(originalHttpRequest, \"http:\");\r\n http.request = proxiedHttpRequest;\r\n http.get = createProxiedGet(proxiedHttpRequest);\r\n\r\n // Patch https\r\n const proxiedHttpsRequest = createProxiedRequest(\r\n originalHttpsRequest,\r\n \"https:\"\r\n );\r\n https.request = proxiedHttpsRequest;\r\n https.get = createProxiedGet(proxiedHttpsRequest);\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"http/https interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the HTTP/HTTPS interceptors\r\n */\r\nexport function uninstallHttpInterceptor(): void {\r\n if (!active) return;\r\n\r\n if (originalHttpRequest) http.request = originalHttpRequest;\r\n if (originalHttpGet) http.get = originalHttpGet;\r\n if (originalHttpsRequest) https.request = originalHttpsRequest;\r\n if (originalHttpsGet) https.get = originalHttpsGet;\r\n\r\n originalHttpRequest = null;\r\n originalHttpGet = null;\r\n originalHttpsRequest = null;\r\n originalHttpsGet = null;\r\n\r\n active = false;\r\n log.debug(\"http/https interceptor removed\");\r\n}\r\n\r\nexport function isHttpInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getHttpStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * ReplayAPI SDK — Global fetch() interceptor\r\n *\r\n * Patches globalThis.fetch to route requests through the ReplayAPI proxy.\r\n * Works with Node.js 18+ native fetch and any polyfills that set globalThis.fetch.\r\n */\r\n\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nconst PROXY_URL = \"http://localhost:8080\";\r\n\r\nlet originalFetch: typeof globalThis.fetch | null = null;\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Install the fetch interceptor\r\n */\r\nexport function installFetchInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"fetch interceptor already installed\");\r\n return;\r\n }\r\n\r\n // Only patch if fetch exists (Node.js 18+)\r\n if (typeof globalThis.fetch !== \"function\") {\r\n log.debug(\"globalThis.fetch not available, skipping fetch interceptor\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n originalFetch = globalThis.fetch;\r\n\r\n globalThis.fetch = async function proxiedFetch(\r\n input: string | URL | Request,\r\n init?: RequestInit\r\n ): Promise<Response> {\r\n try {\r\n // Resolve the target URL\r\n let targetUrl: string;\r\n if (typeof input === \"string\") {\r\n targetUrl = input;\r\n } else if (input instanceof URL) {\r\n targetUrl = input.toString();\r\n } else if (input instanceof Request) {\r\n targetUrl = input.url;\r\n } else {\r\n targetUrl = String(input);\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"fetch skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n // Parse target URL\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"fetch: invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n const proxyPath = parsedTarget.pathname + parsedTarget.search;\r\n const proxiedUrl = `${config.proxyUrl}${proxyPath}`;\r\n\r\n // Build headers\r\n const headers = new Headers(init?.headers || {});\r\n\r\n // If input is a Request, merge its headers too\r\n if (input instanceof Request) {\r\n input.headers.forEach((value, key) => {\r\n if (!headers.has(key)) {\r\n headers.set(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Add ReplayAPI headers\r\n headers.set(\"X-Api-Key\", config.apiKey);\r\n headers.set(\"X-Replay-Target\", targetOrigin);\r\n headers.set(\"X-Replay-Env\", config.environment);\r\n headers.set(\"Host\", parsedTarget.host);\r\n\r\n if (config.sessionId) {\r\n headers.set(\"X-Replay-Session\", config.sessionId);\r\n }\r\n\r\n // Build proxied init\r\n const proxiedInit: RequestInit = {\r\n ...init,\r\n headers,\r\n };\r\n\r\n // If input is a Request, preserve method and body\r\n if (input instanceof Request) {\r\n proxiedInit.method = proxiedInit.method || input.method;\r\n if (!proxiedInit.body && input.body) {\r\n proxiedInit.body = input.body;\r\n }\r\n }\r\n\r\n log.debug(\r\n \"fetch capturing:\",\r\n proxiedInit.method || \"GET\",\r\n targetUrl,\r\n \"→\",\r\n config.proxyUrl\r\n );\r\n stats.totalCaptured++;\r\n\r\n return originalFetch!(proxiedUrl, proxiedInit);\r\n } catch (err) {\r\n log.error(\"fetch interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return originalFetch!(input, init);\r\n }\r\n };\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"fetch interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the fetch interceptor\r\n */\r\nexport function uninstallFetchInterceptor(): void {\r\n if (!active || !originalFetch) return;\r\n\r\n globalThis.fetch = originalFetch;\r\n originalFetch = null;\r\n active = false;\r\n log.debug(\"fetch interceptor removed\");\r\n}\r\n\r\nexport function isFetchInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getFetchStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * @replayapi/node — ReplayAPI SDK for Node.js\r\n *\r\n * Automatically captures outgoing HTTP traffic and routes it through\r\n * the ReplayAPI proxy for recording, analysis, and replay testing.\r\n *\r\n * @example\r\n * ```ts\r\n * import { replayApi } from '@replayapi/node'\r\n *\r\n * // Simplest — just pass your API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: 'rp_your_api_key', environment: 'staging' })\r\n *\r\n * // All outgoing HTTP/fetch calls are now captured automatically\r\n * ```\r\n */\r\n\r\nimport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\nimport {\r\n installHttpInterceptor,\r\n uninstallHttpInterceptor,\r\n isHttpInterceptorActive,\r\n getHttpStats,\r\n} from \"./interceptor-http.js\";\r\nimport {\r\n installFetchInterceptor,\r\n uninstallFetchInterceptor,\r\n isFetchInterceptorActive,\r\n getFetchStats,\r\n} from \"./interceptor-fetch.js\";\r\nimport { setDebug } from \"./logger.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nlet initialized = false;\r\n\r\n/**\r\n * Initialize the ReplayAPI SDK.\r\n *\r\n * Call this once at application startup, before any outgoing HTTP requests.\r\n * The SDK will automatically intercept `http.request`, `https.request`,\r\n * and `fetch` to route traffic through the ReplayAPI proxy.\r\n *\r\n * @example\r\n * ```ts\r\n * // Just an API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: process.env.REPLAY_API_KEY!, environment: 'staging' })\r\n * ```\r\n */\r\nfunction init(configOrApiKey: ReplayApiConfig | string): ReplayApiInstance {\r\n // Accept a plain string as shorthand for { apiKey: string }\r\n const config: ReplayApiConfig =\r\n typeof configOrApiKey === \"string\" ? { apiKey: configOrApiKey } : configOrApiKey;\r\n\r\n if (initialized) {\r\n log.warn(\"replayApi.init() called multiple times — stopping previous instance\");\r\n stop();\r\n }\r\n\r\n // Validate config\r\n if (!config.apiKey) {\r\n throw new Error(\r\n \"[@replayapi/node] apiKey is required. Get one from your ReplayAPI dashboard.\"\r\n );\r\n }\r\n\r\n if (config.disabled) {\r\n log.info(\"SDK disabled via config, skipping initialization\");\r\n return { stop, isActive, getStats };\r\n }\r\n\r\n // Enable debug logging if requested\r\n if (config.debug) {\r\n setDebug(true);\r\n }\r\n\r\n // Resolve environment with env var fallback\r\n config.environment =\r\n config.environment || process.env.REPLAY_ENVIRONMENT || \"development\";\r\n\r\n log.info(`initialized — env: ${config.environment}`);\r\n\r\n // Install interceptors\r\n installHttpInterceptor(config);\r\n installFetchInterceptor(config);\r\n\r\n initialized = true;\r\n\r\n return { stop, isActive, getStats };\r\n}\r\n\r\n/**\r\n * Stop the SDK and restore original HTTP/fetch behavior.\r\n */\r\nfunction stop(): void {\r\n if (!initialized) return;\r\n\r\n uninstallHttpInterceptor();\r\n uninstallFetchInterceptor();\r\n\r\n initialized = false;\r\n log.info(\"stopped — all interceptors removed\");\r\n}\r\n\r\n/**\r\n * Check if the SDK is currently intercepting traffic.\r\n */\r\nfunction isActive(): boolean {\r\n return isHttpInterceptorActive() || isFetchInterceptorActive();\r\n}\r\n\r\n/**\r\n * Get combined capture statistics from all interceptors.\r\n */\r\nfunction getStats(): CaptureStats {\r\n const httpStats = getHttpStats();\r\n const fetchStats = getFetchStats();\r\n\r\n return {\r\n totalCaptured: httpStats.totalCaptured + fetchStats.totalCaptured,\r\n totalSkipped: httpStats.totalSkipped + fetchStats.totalSkipped,\r\n totalErrors: httpStats.totalErrors + fetchStats.totalErrors,\r\n startedAt: httpStats.startedAt < fetchStats.startedAt\r\n ? httpStats.startedAt\r\n : fetchStats.startedAt,\r\n };\r\n}\r\n\r\n/**\r\n * The main ReplayAPI SDK instance.\r\n */\r\nexport const replayApi = {\r\n init,\r\n stop,\r\n isActive,\r\n getStats,\r\n};\r\n\r\n// Named exports for flexibility\r\nexport { init, stop, isActive, getStats };\r\n\r\n// Re-export types\r\nexport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\n"]}
1
+ {"version":3,"sources":["../src/matcher.ts","../src/logger.ts","../src/interceptor-http.ts","../src/interceptor-fetch.ts","../src/index.ts"],"names":["URL","PROXY_URL","active","config","stats","init"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * ReplayAPI SDK — URL matching utilities\r\n */\r\n\r\n/**\r\n * Check if a URL matches any of the given patterns.\r\n * Patterns can be strings (substring match) or RegExp.\r\n */\r\nexport function matchesPatterns(\r\n url: string,\r\n patterns: Array<string | RegExp>\r\n): boolean {\r\n return patterns.some((pattern) => {\r\n if (typeof pattern === \"string\") {\r\n return url.includes(pattern);\r\n }\r\n return pattern.test(url);\r\n });\r\n}\r\n\r\n/**\r\n * Determine if a request URL should be captured based on include/exclude filters.\r\n */\r\nexport function shouldCapture(\r\n url: string,\r\n proxyUrl: string,\r\n include?: Array<string | RegExp>,\r\n exclude?: Array<string | RegExp>\r\n): boolean {\r\n // Never capture requests to the proxy itself\r\n if (url.startsWith(proxyUrl)) {\r\n return false;\r\n }\r\n\r\n // Never capture requests to ReplayAPI internal paths\r\n if (url.includes(\"/__replay/\")) {\r\n return false;\r\n }\r\n\r\n // If include patterns are set, URL must match at least one\r\n if (include && include.length > 0) {\r\n if (!matchesPatterns(url, include)) {\r\n return false;\r\n }\r\n }\r\n\r\n // If exclude patterns are set, URL must not match any\r\n if (exclude && exclude.length > 0) {\r\n if (matchesPatterns(url, exclude)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * ReplayAPI SDK — Simple logger\r\n */\r\n\r\nlet debugEnabled = false;\r\n\r\nexport function setDebug(enabled: boolean): void {\r\n debugEnabled = enabled;\r\n}\r\n\r\nexport function debug(...args: unknown[]): void {\r\n if (debugEnabled) {\r\n console.log(\"[replayapi]\", ...args);\r\n }\r\n}\r\n\r\nexport function info(...args: unknown[]): void {\r\n console.log(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function warn(...args: unknown[]): void {\r\n console.warn(\"[replayapi]\", ...args);\r\n}\r\n\r\nexport function error(...args: unknown[]): void {\r\n console.error(\"[replayapi]\", ...args);\r\n}\r\n","/**\r\n * ReplayAPI SDK — HTTP/HTTPS interceptor\r\n *\r\n * Monkey-patches Node.js http.request and https.request to redirect\r\n * outgoing requests through the ReplayAPI proxy. The proxy captures\r\n * the traffic and forwards it to the original target.\r\n *\r\n * How it works:\r\n * 1. Original request: GET https://api.example.com/users\r\n * 2. SDK rewrites to: GET http://proxy:8080/users\r\n * with headers:\r\n * X-Api-Key: rp_...\r\n * X-Replay-Target: https://api.example.com\r\n * X-Replay-Env: staging\r\n * 3. Proxy captures, forwards to target, returns response transparently\r\n */\r\n\r\nimport http from \"node:http\";\r\nimport https from \"node:https\";\r\nimport { URL } from \"node:url\";\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\n// Store original implementations\r\nlet originalHttpRequest: typeof http.request | null = null;\r\nlet originalHttpGet: typeof http.get | null = null;\r\nlet originalHttpsRequest: typeof https.request | null = null;\r\nlet originalHttpsGet: typeof https.get | null = null;\r\n\r\nconst PROXY_URL = process.env.REPLAY_PROXY_URL || \"http://localhost:8080\";\r\n\r\n// Track state\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Parse the various argument formats that http.request accepts:\r\n * - (url: string, options?, callback?)\r\n * - (url: URL, options?, callback?)\r\n * - (options, callback?)\r\n */\r\nfunction parseRequestArgs(\r\n args: unknown[]\r\n): {\r\n targetUrl: string;\r\n options: http.RequestOptions;\r\n callback?: (res: http.IncomingMessage) => void;\r\n} {\r\n let targetUrl: string;\r\n let options: http.RequestOptions = {};\r\n let callback: ((res: http.IncomingMessage) => void) | undefined;\r\n\r\n if (typeof args[0] === \"string\") {\r\n targetUrl = args[0];\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (args[0] instanceof URL) {\r\n targetUrl = args[0].toString();\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n } else if (typeof args[1] === \"object\" && args[1] !== null) {\r\n options = args[1] as http.RequestOptions;\r\n if (typeof args[2] === \"function\") {\r\n callback = args[2] as (res: http.IncomingMessage) => void;\r\n }\r\n }\r\n } else if (typeof args[0] === \"object\" && args[0] !== null) {\r\n options = args[0] as http.RequestOptions;\r\n const protocol = (options as { protocol?: string }).protocol || \"http:\";\r\n const host = options.hostname || options.host || \"localhost\";\r\n const port = options.port ? `:${options.port}` : \"\";\r\n const path = options.path || \"/\";\r\n targetUrl = `${protocol}//${host}${port}${path}`;\r\n if (typeof args[1] === \"function\") {\r\n callback = args[1] as (res: http.IncomingMessage) => void;\r\n }\r\n } else {\r\n targetUrl = \"\";\r\n }\r\n\r\n return { targetUrl, options, callback };\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.request / https.request\r\n */\r\nfunction createProxiedRequest(\r\n originalFn: typeof http.request,\r\n defaultProtocol: \"http:\" | \"https:\"\r\n): typeof http.request {\r\n return function proxiedRequest(\r\n ...args: unknown[]\r\n ): http.ClientRequest {\r\n try {\r\n const { targetUrl, options, callback } = parseRequestArgs(args);\r\n\r\n if (!targetUrl) {\r\n log.debug(\"could not parse request URL, passing through\");\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n // Parse the proxy URL\r\n const proxyParsed = new URL(config.proxyUrl);\r\n\r\n // Parse the target URL to extract origin and path\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n\r\n // Build proxied options: send to proxy, with X-Replay-Target header\r\n const proxiedOptions: http.RequestOptions = {\r\n ...options,\r\n protocol: proxyParsed.protocol,\r\n hostname: proxyParsed.hostname,\r\n port: proxyParsed.port || (proxyParsed.protocol === \"https:\" ? 443 : 80),\r\n path: parsedTarget.pathname + parsedTarget.search,\r\n headers: {\r\n ...options.headers,\r\n \"X-Api-Key\": config.apiKey,\r\n \"X-Replay-Target\": targetOrigin,\r\n \"X-Replay-Env\": config.environment,\r\n // Preserve the original Host header\r\n Host: parsedTarget.host,\r\n },\r\n };\r\n\r\n // Add session ID if configured\r\n if (config.sessionId) {\r\n (proxiedOptions.headers as Record<string, string>)[\"X-Replay-Session\"] =\r\n config.sessionId;\r\n }\r\n\r\n // Set timeout if configured\r\n if (config.timeout) {\r\n proxiedOptions.timeout = config.timeout;\r\n }\r\n\r\n log.debug(\"capturing:\", options.method || \"GET\", targetUrl, \"→\", config.proxyUrl);\r\n stats.totalCaptured++;\r\n\r\n // Use http.request (not https) since we're talking to the proxy over HTTP\r\n const proxyUrl = new URL(`${proxiedOptions.protocol}//${proxiedOptions.hostname}:${proxiedOptions.port}${proxiedOptions.path}`);\r\n return originalHttpRequest!.call(http, proxyUrl, proxiedOptions, callback);\r\n } catch (err) {\r\n log.error(\"interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return (originalFn as Function).apply(\r\n defaultProtocol === \"https:\" ? https : http,\r\n args\r\n ) as http.ClientRequest;\r\n }\r\n } as typeof http.request;\r\n}\r\n\r\n/**\r\n * Create a proxied version of http.get / https.get\r\n */\r\nfunction createProxiedGet(\r\n proxiedRequest: typeof http.request\r\n): typeof http.get {\r\n return function proxiedGet(...args: unknown[]): http.ClientRequest {\r\n const req = (proxiedRequest as Function)(...args) as http.ClientRequest;\r\n req.end();\r\n return req;\r\n } as typeof http.get;\r\n}\r\n\r\n/**\r\n * Install the HTTP/HTTPS interceptors\r\n */\r\nexport function installHttpInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"interceptor already installed, call stop() first\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n // Save originals\r\n originalHttpRequest = http.request;\r\n originalHttpGet = http.get;\r\n originalHttpsRequest = https.request;\r\n originalHttpsGet = https.get;\r\n\r\n // Patch http\r\n const proxiedHttpRequest = createProxiedRequest(originalHttpRequest, \"http:\");\r\n http.request = proxiedHttpRequest;\r\n http.get = createProxiedGet(proxiedHttpRequest);\r\n\r\n // Patch https\r\n const proxiedHttpsRequest = createProxiedRequest(\r\n originalHttpsRequest,\r\n \"https:\"\r\n );\r\n https.request = proxiedHttpsRequest;\r\n https.get = createProxiedGet(proxiedHttpsRequest);\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"http/https interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the HTTP/HTTPS interceptors\r\n */\r\nexport function uninstallHttpInterceptor(): void {\r\n if (!active) return;\r\n\r\n if (originalHttpRequest) http.request = originalHttpRequest;\r\n if (originalHttpGet) http.get = originalHttpGet;\r\n if (originalHttpsRequest) https.request = originalHttpsRequest;\r\n if (originalHttpsGet) https.get = originalHttpsGet;\r\n\r\n originalHttpRequest = null;\r\n originalHttpGet = null;\r\n originalHttpsRequest = null;\r\n originalHttpsGet = null;\r\n\r\n active = false;\r\n log.debug(\"http/https interceptor removed\");\r\n}\r\n\r\nexport function isHttpInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getHttpStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * ReplayAPI SDK — Global fetch() interceptor\r\n *\r\n * Patches globalThis.fetch to route requests through the ReplayAPI proxy.\r\n * Works with Node.js 18+ native fetch and any polyfills that set globalThis.fetch.\r\n */\r\n\r\nimport type { ReplayApiConfig, CaptureStats } from \"./types.js\";\r\nimport { shouldCapture } from \"./matcher.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nconst PROXY_URL = process.env.REPLAY_PROXY_URL || \"http://localhost:8080\";\r\n\r\nlet originalFetch: typeof globalThis.fetch | null = null;\r\nlet active = false;\r\nlet config: Required<\r\n Pick<ReplayApiConfig, \"apiKey\" | \"environment\">\r\n> &\r\n ReplayApiConfig & { proxyUrl: string };\r\n\r\nconst stats: CaptureStats = {\r\n totalCaptured: 0,\r\n totalSkipped: 0,\r\n totalErrors: 0,\r\n startedAt: new Date(),\r\n};\r\n\r\n/**\r\n * Install the fetch interceptor\r\n */\r\nexport function installFetchInterceptor(cfg: ReplayApiConfig): void {\r\n if (active) {\r\n log.warn(\"fetch interceptor already installed\");\r\n return;\r\n }\r\n\r\n // Only patch if fetch exists (Node.js 18+)\r\n if (typeof globalThis.fetch !== \"function\") {\r\n log.debug(\"globalThis.fetch not available, skipping fetch interceptor\");\r\n return;\r\n }\r\n\r\n config = {\r\n ...cfg,\r\n proxyUrl: PROXY_URL,\r\n environment: cfg.environment || \"development\",\r\n };\r\n\r\n originalFetch = globalThis.fetch;\r\n\r\n globalThis.fetch = async function proxiedFetch(\r\n input: string | URL | Request,\r\n init?: RequestInit\r\n ): Promise<Response> {\r\n try {\r\n // Resolve the target URL\r\n let targetUrl: string;\r\n if (typeof input === \"string\") {\r\n targetUrl = input;\r\n } else if (input instanceof URL) {\r\n targetUrl = input.toString();\r\n } else if (input instanceof Request) {\r\n targetUrl = input.url;\r\n } else {\r\n targetUrl = String(input);\r\n }\r\n\r\n // Check if this URL should be captured\r\n if (\r\n !shouldCapture(\r\n targetUrl,\r\n config.proxyUrl,\r\n config.include,\r\n config.exclude\r\n )\r\n ) {\r\n log.debug(\"fetch skipping (filtered):\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n // Parse target URL\r\n let parsedTarget: URL;\r\n try {\r\n parsedTarget = new URL(targetUrl);\r\n } catch {\r\n log.debug(\"fetch: invalid URL, passing through:\", targetUrl);\r\n stats.totalSkipped++;\r\n return originalFetch!(input, init);\r\n }\r\n\r\n const targetOrigin = `${parsedTarget.protocol}//${parsedTarget.host}`;\r\n const proxyPath = parsedTarget.pathname + parsedTarget.search;\r\n const proxiedUrl = `${config.proxyUrl}${proxyPath}`;\r\n\r\n // Build headers\r\n const headers = new Headers(init?.headers || {});\r\n\r\n // If input is a Request, merge its headers too\r\n if (input instanceof Request) {\r\n input.headers.forEach((value, key) => {\r\n if (!headers.has(key)) {\r\n headers.set(key, value);\r\n }\r\n });\r\n }\r\n\r\n // Add ReplayAPI headers\r\n headers.set(\"X-Api-Key\", config.apiKey);\r\n headers.set(\"X-Replay-Target\", targetOrigin);\r\n headers.set(\"X-Replay-Env\", config.environment);\r\n headers.set(\"Host\", parsedTarget.host);\r\n\r\n if (config.sessionId) {\r\n headers.set(\"X-Replay-Session\", config.sessionId);\r\n }\r\n\r\n // Build proxied init\r\n const proxiedInit: RequestInit = {\r\n ...init,\r\n headers,\r\n };\r\n\r\n // If input is a Request, preserve method and body\r\n if (input instanceof Request) {\r\n proxiedInit.method = proxiedInit.method || input.method;\r\n if (!proxiedInit.body && input.body) {\r\n proxiedInit.body = input.body;\r\n }\r\n }\r\n\r\n log.debug(\r\n \"fetch capturing:\",\r\n proxiedInit.method || \"GET\",\r\n targetUrl,\r\n \"→\",\r\n config.proxyUrl\r\n );\r\n stats.totalCaptured++;\r\n\r\n return originalFetch!(proxiedUrl, proxiedInit);\r\n } catch (err) {\r\n log.error(\"fetch interceptor error, passing through:\", err);\r\n stats.totalErrors++;\r\n return originalFetch!(input, init);\r\n }\r\n };\r\n\r\n // Reset stats\r\n stats.totalCaptured = 0;\r\n stats.totalSkipped = 0;\r\n stats.totalErrors = 0;\r\n stats.startedAt = new Date();\r\n\r\n active = true;\r\n log.debug(\"fetch interceptor installed\");\r\n}\r\n\r\n/**\r\n * Uninstall the fetch interceptor\r\n */\r\nexport function uninstallFetchInterceptor(): void {\r\n if (!active || !originalFetch) return;\r\n\r\n globalThis.fetch = originalFetch;\r\n originalFetch = null;\r\n active = false;\r\n log.debug(\"fetch interceptor removed\");\r\n}\r\n\r\nexport function isFetchInterceptorActive(): boolean {\r\n return active;\r\n}\r\n\r\nexport function getFetchStats(): CaptureStats {\r\n return { ...stats };\r\n}\r\n","/**\r\n * @replayapi/node — ReplayAPI SDK for Node.js\r\n *\r\n * Automatically captures outgoing HTTP traffic and routes it through\r\n * the ReplayAPI proxy for recording, analysis, and replay testing.\r\n *\r\n * @example\r\n * ```ts\r\n * import { replayApi } from '@replayapi/node'\r\n *\r\n * // Simplest — just pass your API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: 'rp_your_api_key', environment: 'staging' })\r\n *\r\n * // All outgoing HTTP/fetch calls are now captured automatically\r\n * ```\r\n */\r\n\r\nimport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\nimport {\r\n installHttpInterceptor,\r\n uninstallHttpInterceptor,\r\n isHttpInterceptorActive,\r\n getHttpStats,\r\n} from \"./interceptor-http.js\";\r\nimport {\r\n installFetchInterceptor,\r\n uninstallFetchInterceptor,\r\n isFetchInterceptorActive,\r\n getFetchStats,\r\n} from \"./interceptor-fetch.js\";\r\nimport { setDebug } from \"./logger.js\";\r\nimport * as log from \"./logger.js\";\r\n\r\nlet initialized = false;\r\n\r\n/**\r\n * Initialize the ReplayAPI SDK.\r\n *\r\n * Call this once at application startup, before any outgoing HTTP requests.\r\n * The SDK will automatically intercept `http.request`, `https.request`,\r\n * and `fetch` to route traffic through the ReplayAPI proxy.\r\n *\r\n * @example\r\n * ```ts\r\n * // Just an API key\r\n * replayApi.init('rp_your_api_key')\r\n *\r\n * // Or with options\r\n * replayApi.init({ apiKey: process.env.REPLAY_API_KEY!, environment: 'staging' })\r\n * ```\r\n */\r\nfunction init(configOrApiKey: ReplayApiConfig | string): ReplayApiInstance {\r\n // Accept a plain string as shorthand for { apiKey: string }\r\n const config: ReplayApiConfig =\r\n typeof configOrApiKey === \"string\" ? { apiKey: configOrApiKey } : configOrApiKey;\r\n\r\n if (initialized) {\r\n log.warn(\"replayApi.init() called multiple times — stopping previous instance\");\r\n stop();\r\n }\r\n\r\n // Validate config\r\n if (!config.apiKey) {\r\n throw new Error(\r\n \"[@replayapi/node] apiKey is required. Get one from your ReplayAPI dashboard.\"\r\n );\r\n }\r\n\r\n if (config.disabled) {\r\n log.info(\"SDK disabled via config, skipping initialization\");\r\n return { stop, isActive, getStats };\r\n }\r\n\r\n // Enable debug logging if requested\r\n if (config.debug) {\r\n setDebug(true);\r\n }\r\n\r\n // Resolve environment with env var fallback\r\n config.environment =\r\n config.environment || process.env.REPLAY_ENVIRONMENT || \"development\";\r\n\r\n log.info(`initialized — env: ${config.environment}`);\r\n\r\n // Install interceptors\r\n installHttpInterceptor(config);\r\n installFetchInterceptor(config);\r\n\r\n initialized = true;\r\n\r\n return { stop, isActive, getStats };\r\n}\r\n\r\n/**\r\n * Stop the SDK and restore original HTTP/fetch behavior.\r\n */\r\nfunction stop(): void {\r\n if (!initialized) return;\r\n\r\n uninstallHttpInterceptor();\r\n uninstallFetchInterceptor();\r\n\r\n initialized = false;\r\n log.info(\"stopped — all interceptors removed\");\r\n}\r\n\r\n/**\r\n * Check if the SDK is currently intercepting traffic.\r\n */\r\nfunction isActive(): boolean {\r\n return isHttpInterceptorActive() || isFetchInterceptorActive();\r\n}\r\n\r\n/**\r\n * Get combined capture statistics from all interceptors.\r\n */\r\nfunction getStats(): CaptureStats {\r\n const httpStats = getHttpStats();\r\n const fetchStats = getFetchStats();\r\n\r\n return {\r\n totalCaptured: httpStats.totalCaptured + fetchStats.totalCaptured,\r\n totalSkipped: httpStats.totalSkipped + fetchStats.totalSkipped,\r\n totalErrors: httpStats.totalErrors + fetchStats.totalErrors,\r\n startedAt: httpStats.startedAt < fetchStats.startedAt\r\n ? httpStats.startedAt\r\n : fetchStats.startedAt,\r\n };\r\n}\r\n\r\n/**\r\n * The main ReplayAPI SDK instance.\r\n */\r\nexport const replayApi = {\r\n init,\r\n stop,\r\n isActive,\r\n getStats,\r\n};\r\n\r\n// Named exports for flexibility\r\nexport { init, stop, isActive, getStats };\r\n\r\n// Re-export types\r\nexport type { ReplayApiConfig, ReplayApiInstance, CaptureStats } from \"./types.js\";\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thaparoyal/replayapi",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "ReplayAPI SDK for Node.js — Capture HTTP traffic automatically",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",