@aeres/farol-web 0.0.0-stage → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/serialize.ts","../src/network.ts","../src/index.ts"],"sourcesContent":["/** Redaction happens before queuing, persistence, or transmission. */\nexport const REDACTED = \"[REDACTED]\";\nconst sensitiveKey =\n /(?:authorization|cookie|password|passwd|secret|token|api[-_]?key|credential|session[-_]?id|private[-_]?key)/i;\nexport const isSensitiveKey = (key: string): boolean => sensitiveKey.test(key);\n\nexport function redactUrl(value: string): string {\n try {\n const url = new URL(value, \"http://farol.invalid\");\n if (url.username) url.username = REDACTED;\n if (url.password) url.password = REDACTED;\n for (const key of [...url.searchParams.keys()])\n if (isSensitiveKey(key)) url.searchParams.set(key, REDACTED);\n if (\n url.hash &&\n /(?:token|password|secret|api[-_]?key|code)=/i.test(url.hash)\n )\n url.hash = REDACTED;\n const result = url.toString();\n return result.startsWith(\"http://farol.invalid\")\n ? `${url.pathname}${url.search}${url.hash}`\n : result;\n } catch {\n return value.replace(\n /([?&](?:[^=&]*(?:token|password|secret|api[-_]?key)[^=&]*)=)[^&#\\s]*/gi,\n `$1${REDACTED}`,\n );\n }\n}\n\nfunction redactText(value: string, max: number): string {\n let text = value;\n // Parse JSON before trimming so secrets cannot hide in nested encoded strings.\n if (text.length <= 65_536 && /^[\\s]*[\\[{]/.test(text)) {\n try {\n const encoded = JSON.stringify(\n safeSerialize(JSON.parse(text), { maxString: max }),\n );\n return encoded.length > max\n ? `${encoded.slice(0, max)}…[truncated]`\n : encoded;\n } catch {\n /* ordinary text */\n }\n }\n text = text.replace(/\\b(?:https?|wss?):\\/\\/[^\\s\"'<>]+/gi, (url) =>\n redactUrl(url),\n );\n if (/^(?:\\/|[a-z][a-z\\d+.-]*:\\/\\/)/i.test(text)) text = redactUrl(text);\n text = text\n .replace(/\\b(Bearer|Basic)\\s+[A-Za-z\\d+/_=.-]+/gi, `$1 ${REDACTED}`)\n .replace(\n /((?:(?:password|passwd|secret|token|api[-_]?key|authorization|cookie)[\\w-]{0,40})[\"']?\\s*[:=]\\s*[\"']?)[^\\s,\"'&;}]+/gi,\n `$1${REDACTED}`,\n );\n return text.length > max ? `${text.slice(0, max)}…[truncated]` : text;\n}\n\nexport interface SerializeLimits {\n maxDepth?: number;\n maxEntries?: number;\n maxString?: number;\n}\n/** Serializable, bounded, circular-safe data. Does not invoke user getters or toJSON. */\nexport function safeSerialize(\n value: unknown,\n limits: SerializeLimits = {},\n): unknown {\n const depthLimit = limits.maxDepth ?? 6;\n const entriesLimit = limits.maxEntries ?? 80;\n const stringLimit = limits.maxString ?? 4_096;\n const seen = new WeakSet<object>();\n let budget = 600;\n function visit(item: unknown, depth: number, key = \"\"): unknown {\n if (isSensitiveKey(key)) return REDACTED;\n if (budget-- <= 0) return \"[Truncated]\";\n if (item === null || typeof item === \"boolean\" || typeof item === \"number\")\n return typeof item === \"number\" && !Number.isFinite(item)\n ? String(item)\n : item;\n if (typeof item === \"string\") return redactText(item, stringLimit);\n if (typeof item === \"bigint\") return `${item}n`;\n if (typeof item === \"undefined\") return \"[undefined]\";\n if (typeof item === \"function\")\n return `[Function ${item.name || \"anonymous\"}]`;\n if (typeof item === \"symbol\") return String(item);\n if (depth >= depthLimit) return \"[Max depth]\";\n const obj = item as object;\n if (seen.has(obj)) return \"[Circular]\";\n seen.add(obj);\n if (obj instanceof Error)\n return {\n name: obj.name,\n message: redactText(obj.message, stringLimit),\n stack: obj.stack ? redactText(obj.stack, stringLimit) : undefined,\n ...(\"cause\" in obj ? { cause: visit(obj.cause, depth + 1) } : {}),\n };\n if (obj instanceof Date)\n return Number.isFinite(obj.getTime())\n ? obj.toISOString()\n : \"Invalid Date\";\n if (typeof URL !== \"undefined\" && obj instanceof URL)\n return redactUrl(obj.href);\n if (typeof Headers !== \"undefined\" && obj instanceof Headers)\n return visit(Object.fromEntries(obj.entries()), depth + 1);\n if (typeof Element !== \"undefined\" && obj instanceof Element)\n return `<${obj.tagName.toLowerCase()}${obj.id ? `#${obj.id}` : \"\"}>`;\n if (typeof Blob !== \"undefined\" && obj instanceof Blob)\n return `[Blob ${obj.type || \"binary\"}; ${obj.size} bytes]`;\n if (obj instanceof Map) {\n const entries: unknown[] = [];\n for (const [mapKey, mapValue] of obj) {\n if (entries.length >= entriesLimit) break;\n entries.push([\n visit(mapKey, depth + 1),\n visit(mapValue, depth + 1, typeof mapKey === \"string\" ? mapKey : \"\"),\n ]);\n }\n if (obj.size > entriesLimit)\n entries.push(`[${obj.size - entriesLimit} more items]`);\n return entries;\n }\n if (obj instanceof Set) {\n const items: unknown[] = [];\n for (const value of obj) {\n if (items.length >= entriesLimit) break;\n items.push(visit(value, depth + 1));\n }\n if (obj.size > entriesLimit)\n items.push(`[${obj.size - entriesLimit} more items]`);\n return items;\n }\n if (ArrayBuffer.isView(obj))\n return `[${obj.constructor.name}; ${obj.byteLength} bytes]`;\n if (Array.isArray(obj))\n return obj\n .slice(0, entriesLimit)\n .map((child) => visit(child, depth + 1))\n .concat(\n obj.length > entriesLimit\n ? [`[${obj.length - entriesLimit} more items]`]\n : [],\n );\n const result: Record<string, unknown> = {};\n let descriptors: Record<string, PropertyDescriptor>;\n try {\n descriptors = Object.getOwnPropertyDescriptors(obj);\n } catch {\n return \"[Uninspectable]\";\n }\n const keys = Object.keys(descriptors).filter(\n (k) => descriptors[k].enumerable,\n );\n for (const property of keys.slice(0, entriesLimit)) {\n const desc = descriptors[property];\n Object.defineProperty(result, property, {\n value: isSensitiveKey(property)\n ? REDACTED\n : \"value\" in desc\n ? visit(desc.value, depth + 1, property)\n : \"[Getter]\",\n enumerable: true,\n configurable: true,\n writable: true,\n });\n }\n if (keys.length > entriesLimit)\n result[\"…\"] = `${keys.length - entriesLimit} more keys`;\n return result;\n }\n try {\n return visit(value, 0);\n } catch {\n return \"[Unserializable]\";\n }\n}\n\nconst serializationMarker =\n /\\[(?:REDACTED|Max depth|Circular|Truncated(?:[^\\]]*)?|undefined|Uninspectable|Unserializable|Getter|Function(?:[^\\]]*)|Blob(?:[^\\]]*)|(?:[A-Za-z]\\w*Array|DataView); \\d+ bytes|\\d+ more items|Body (?:omitted|unavailable)(?:[^\\]]*))\\]/i;\n/** Conservative guard for values copied from a lossy/redacted snapshot, including encoded JSON/URLs. */\nexport function containsSerializationMarkers(value: unknown): boolean {\n const seen = new WeakSet<object>();\n let budget = 10_000;\n function check(item: unknown, depth: number): boolean {\n if (budget-- <= 0 || depth > 40) return true;\n if (typeof item === \"string\") {\n if (\n serializationMarker.test(item) ||\n /%5b(?:REDACTED|Max%20depth|Circular|Truncated)%5d/i.test(item)\n )\n return true;\n if (/^(?:NaN|[+-]?Infinity|-?\\d+n|Symbol\\([^)]*\\)|<[^<> ]+>)$/.test(item))\n return true;\n if (/^\\s*[\\[{]/.test(item) && item.length <= 65_536) {\n try {\n return check(JSON.parse(item), depth + 1);\n } catch {\n /* ordinary text */\n }\n }\n return false;\n }\n if (item === null || typeof item === \"boolean\") return false;\n if (typeof item === \"number\") return !Number.isFinite(item);\n if (typeof item !== \"object\") return true;\n if (seen.has(item)) return true;\n seen.add(item);\n if (Array.isArray(item))\n return item.some((entry) => check(entry, depth + 1));\n let descriptors: Record<string, PropertyDescriptor>;\n try {\n descriptors = Object.getOwnPropertyDescriptors(item);\n } catch {\n return true;\n }\n for (const [key, descriptor] of Object.entries(descriptors)) {\n if (!descriptor.enumerable) continue;\n if (key === \"…\" || (key === \"truncated\" && descriptor.value === true))\n return true;\n if (!(\"value\" in descriptor) || check(descriptor.value, depth + 1))\n return true;\n }\n return false;\n }\n try {\n return check(value, 0);\n } catch {\n return true;\n }\n}\n","import type { MockRule } from \"./types\";\n\nexport interface NetworkControls {\n offline: boolean;\n latency: number;\n mocks: Map<string, MockRule>;\n}\ninterface NetworkContext {\n win: Window & typeof globalThis;\n endpoint: string;\n controls: NetworkControls;\n captureBodies: boolean;\n maxBodyBytes: number;\n emit(data: Record<string, unknown>): void;\n}\nconst textContent = /(?:json|text|xml|javascript|x-www-form-urlencoded)/i;\nconst now = () =>\n typeof performance !== \"undefined\" ? performance.now() : Date.now();\nexport function matchMock(\n rules: Map<string, MockRule>,\n url: string,\n method: string,\n): MockRule | undefined {\n for (const rule of rules.values()) {\n if (\n rule.method !== \"*\" &&\n rule.method.toUpperCase() !== method.toUpperCase()\n )\n continue;\n const expression = `^${rule.url\n .split(\"*\")\n .map((p) => p.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n .join(\".*\")}$`;\n try {\n if (\n new RegExp(expression).test(url) ||\n new RegExp(expression).test(new URL(url).pathname)\n )\n return rule;\n } catch {\n /* invalid URL */\n }\n }\n return undefined;\n}\nasync function readBody(\n stream: ReadableStream<Uint8Array> | null,\n headers: Headers,\n max: number,\n): Promise<unknown> {\n if (!stream) return undefined;\n const contentType = headers.get(\"content-type\") || \"\";\n if (!textContent.test(contentType) || /event-stream/i.test(contentType)) {\n void stream.cancel().catch(() => {});\n return \"[Body omitted: non-text or streaming content]\";\n }\n const length = Number(headers.get(\"content-length\"));\n if (length > max) {\n void stream.cancel().catch(() => {});\n return `[Body omitted: ${length} bytes]`;\n }\n const reader = stream.getReader();\n const decoder = new TextDecoder();\n let size = 0;\n let text = \"\";\n try {\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) break;\n size += chunk.value.byteLength;\n if (size > max) {\n void reader.cancel().catch(() => {});\n return \"[Body omitted: size limit]\";\n }\n text += decoder.decode(chunk.value, { stream: true });\n }\n text += decoder.decode();\n if (/json/i.test(contentType)) {\n try {\n return JSON.parse(text);\n } catch {\n /* invalid JSON */\n }\n }\n return text;\n } catch {\n return \"[Body unavailable]\";\n } finally {\n try {\n reader.releaseLock();\n } catch {\n /* canceled reader */\n }\n }\n}\nfunction requestBody(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n max: number,\n): Promise<unknown> {\n if (init?.body != null) {\n if (typeof init.body === \"string\")\n return Promise.resolve(\n new TextEncoder().encode(init.body).length <= max\n ? init.body\n : \"[Body omitted: size limit]\",\n );\n if (init.body instanceof URLSearchParams)\n return Promise.resolve(Object.fromEntries(init.body.entries()));\n if (typeof FormData !== \"undefined\" && init.body instanceof FormData)\n return Promise.resolve(\"[Body omitted: multipart data]\");\n return Promise.resolve(\"[Body omitted: binary/stream content]\");\n }\n if (typeof Request !== \"undefined\" && input instanceof Request) {\n try {\n const clone = input.clone();\n return readBody(clone.body, clone.headers, max);\n } catch {\n return Promise.resolve(\"[Body unavailable]\");\n }\n }\n return Promise.resolve(undefined);\n}\nfunction mockBody(rule: MockRule): string | null {\n if (rule.status === 204 || rule.status === 205 || rule.status === 304)\n return null;\n return typeof rule.body === \"string\"\n ? rule.body\n : JSON.stringify(rule.body ?? null);\n}\n/** Every wrapper delegates native semantics unless an explicit debug simulation is active. */\nexport function instrumentNetwork(ctx: NetworkContext): () => void {\n const { win, controls } = ctx;\n let stopped = false;\n const cleanups = new Set<() => void>();\n const collector = new URL(ctx.endpoint);\n collector.protocol = collector.protocol === \"wss:\" ? \"https:\" : \"http:\";\n const internalPaths = new Set([\n collector.pathname,\n \"/ws\",\n \"/rn\",\n \"/api/config\",\n \"/api/demo/config\",\n \"/api/health\",\n ]);\n const excluded = (url: string) => {\n try {\n const u = new URL(url, win.location.href);\n // A bundled demo can share the broker's origin. Only Farol control paths\n // bypass instrumentation; application requests still support inspection/mocks.\n return u.origin === collector.origin && internalPaths.has(u.pathname);\n } catch {\n return false;\n }\n };\n const emit = (data: Record<string, unknown>) => {\n if (!stopped) ctx.emit(data);\n };\n const wait = (ms: number, signal?: AbortSignal | null) =>\n new Promise<void>((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new DOMException(\"Aborted\", \"AbortError\"));\n return;\n }\n const done = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", abort);\n cleanups.delete(cancel);\n resolve();\n };\n const abort = () => {\n clearTimeout(timer);\n signal?.removeEventListener(\"abort\", abort);\n cleanups.delete(cancel);\n reject(signal?.reason ?? new DOMException(\"Aborted\", \"AbortError\"));\n };\n const timer = setTimeout(done, ms);\n const cancel = () => done();\n cleanups.add(cancel);\n signal?.addEventListener(\"abort\", abort, { once: true });\n });\n const originalFetch = win.fetch;\n if (typeof originalFetch === \"function\") {\n const wrapped: typeof fetch = async function (input, init) {\n const rawUrl =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n let url: string;\n try {\n url = new URL(rawUrl, win.location.href).href;\n } catch {\n return originalFetch.call(win, input, init);\n }\n if (excluded(url) || stopped) return originalFetch.call(win, input, init);\n const req =\n typeof Request !== \"undefined\" && input instanceof Request\n ? input\n : undefined;\n const method = (init?.method || req?.method || \"GET\").toUpperCase();\n const headers = new Headers(init?.headers ?? req?.headers);\n const start = now();\n const rule = matchMock(controls.mocks, url, method);\n const signal = init?.signal ?? req?.signal;\n const body = ctx.captureBodies\n ? requestBody(input, init, ctx.maxBodyBytes)\n : Promise.resolve(undefined);\n const base = {\n method,\n url,\n requestHeaders: Object.fromEntries(headers.entries()),\n mocked: Boolean(rule),\n };\n try {\n if (controls.latency > 0 || (rule?.delay ?? 0) > 0)\n await wait(controls.latency + (rule?.delay ?? 0), signal);\n if (!stopped && controls.offline)\n throw new TypeError(\"Farol: simulated offline network\");\n if (signal?.aborted)\n throw signal.reason ?? new DOMException(\"Aborted\", \"AbortError\");\n const response =\n !stopped && rule\n ? new Response(mockBody(rule), {\n status: rule.status,\n headers: {\n \"content-type\":\n typeof rule.body === \"string\"\n ? \"text/plain\"\n : \"application/json\",\n \"x-farol-mock\": rule.id,\n },\n })\n : await originalFetch.call(win, input, init);\n const duration = now() - start;\n const responseHeaders = Object.fromEntries(response.headers.entries());\n let responseBody: Promise<unknown> = Promise.resolve(undefined);\n if (ctx.captureBodies) {\n try {\n const clone = response.clone();\n responseBody = readBody(\n clone.body,\n clone.headers,\n ctx.maxBodyBytes,\n );\n } catch {\n responseBody = Promise.resolve(\"[Body unavailable]\");\n }\n }\n void Promise.all([body, responseBody])\n .then(([requestBody, responseBody]) =>\n emit({\n ...base,\n status: response.status,\n duration,\n responseHeaders,\n ...(ctx.captureBodies ? { requestBody, responseBody } : {}),\n }),\n )\n .catch(() => {});\n return response;\n } catch (error) {\n void body\n .then((requestBody) =>\n emit({\n ...base,\n status: 0,\n duration: now() - start,\n error: error instanceof Error ? error.message : String(error),\n ...(ctx.captureBodies ? { requestBody } : {}),\n }),\n )\n .catch(() => {});\n throw error;\n }\n };\n win.fetch = wrapped;\n cleanups.add(() => {\n if (win.fetch === wrapped) win.fetch = originalFetch;\n });\n }\n if (typeof win.XMLHttpRequest === \"function\") {\n const proto = win.XMLHttpRequest.prototype;\n const originalOpen = proto.open;\n const originalSend = proto.send;\n const originalSetHeader = proto.setRequestHeader;\n const originalAbort = proto.abort;\n interface XhrInfo {\n method: string;\n url: string;\n headers: Record<string, string>;\n finish?: () => void;\n cancel?: () => void;\n overrides?: string[];\n }\n const requests = new WeakMap<XMLHttpRequest, XhrInfo>();\n // Keep teardown access without strongly retaining completed mocked XHRs.\n const mockRefs = new Set<WeakRef<XMLHttpRequest>>();\n const refsByRequest = new WeakMap<\n XMLHttpRequest,\n WeakRef<XMLHttpRequest>\n >();\n const finalizer = new FinalizationRegistry<WeakRef<XMLHttpRequest>>((ref) =>\n mockRefs.delete(ref),\n );\n function restoreOverrides(xhr: XMLHttpRequest) {\n const request = requests.get(xhr);\n for (const key of request?.overrides ?? []) {\n try {\n delete (xhr as unknown as Record<string, unknown>)[key];\n } catch {}\n }\n if (request) request.overrides = [];\n const ref = refsByRequest.get(xhr);\n if (ref) {\n mockRefs.delete(ref);\n finalizer.unregister(ref);\n refsByRequest.delete(xhr);\n }\n }\n cleanups.add(() => {\n for (const ref of mockRefs) {\n const xhr = ref.deref();\n if (xhr) restoreOverrides(xhr);\n else finalizer.unregister(ref);\n }\n mockRefs.clear();\n });\n const open = function (\n this: XMLHttpRequest,\n method: string,\n url: string | URL,\n ...rest: unknown[]\n ) {\n const previous = requests.get(this);\n previous?.cancel?.();\n restoreOverrides(this);\n requests.set(this, {\n method: method.toUpperCase(),\n url: new URL(String(url), win.location.href).href,\n headers: {},\n });\n return (originalOpen as Function).call(this, method, url, ...rest);\n } as typeof proto.open;\n const setHeader: typeof proto.setRequestHeader = function (\n this: XMLHttpRequest,\n key,\n value,\n ) {\n const request = requests.get(this);\n const result = originalSetHeader.call(this, key, value);\n if (request) request.headers[key] = value;\n return result;\n };\n const send: typeof proto.send = function (this: XMLHttpRequest, body) {\n const request = requests.get(this);\n if (!request || excluded(request.url) || stopped)\n return originalSend.call(this, body);\n const start = now();\n const xhr = this;\n const rule = matchMock(controls.mocks, request.url, request.method);\n let completed = false;\n const finish = () => {\n if (completed) return;\n completed = true;\n xhr.removeEventListener(\"loadend\", finish);\n cleanups.delete(removeListener);\n let responseHeaders: Record<string, string> = {};\n let responseBody: unknown;\n try {\n responseHeaders = Object.fromEntries(\n xhr\n .getAllResponseHeaders()\n .trim()\n .split(/[\\r\\n]+/)\n .filter(Boolean)\n .map((h) => {\n const i = h.indexOf(\":\");\n return [h.slice(0, i).trim(), h.slice(i + 1).trim()];\n }),\n );\n } catch {}\n if (ctx.captureBodies) {\n try {\n responseBody =\n xhr.responseType === \"json\"\n ? xhr.response\n : !xhr.responseType || xhr.responseType === \"text\"\n ? xhr.responseText.length <= ctx.maxBodyBytes\n ? xhr.responseText\n : \"[Body omitted: size limit]\"\n : \"[Body omitted: binary content]\";\n } catch {\n responseBody = \"[Body unavailable]\";\n }\n }\n const requestBody =\n typeof body === \"string\"\n ? body.length <= ctx.maxBodyBytes\n ? body\n : \"[Body omitted: size limit]\"\n : body == null\n ? undefined\n : \"[Body omitted: non-text content]\";\n emit({\n method: request.method,\n url: request.url,\n status: xhr.status,\n duration: now() - start,\n requestHeaders: request.headers,\n responseHeaders,\n mocked: Boolean(rule),\n ...(xhr.status === 0\n ? { error: \"XHR failed, aborted, or simulated offline\" }\n : {}),\n ...(ctx.captureBodies ? { requestBody, responseBody } : {}),\n });\n };\n const removeListener = () => xhr.removeEventListener(\"loadend\", finish);\n xhr.addEventListener(\"loadend\", finish, { once: true });\n cleanups.add(removeListener);\n request.finish = finish;\n const dispatch = (name: string) => xhr.dispatchEvent(new Event(name));\n const simulate = () => {\n const offline = controls.offline;\n if (!offline && !rule) {\n originalSend.call(xhr, body);\n return;\n }\n const content = rule ? (mockBody(rule) ?? \"\") : \"\";\n const values: Record<string, unknown> = {\n readyState: 4,\n status: offline ? 0 : rule!.status,\n statusText: offline ? \"\" : \"Farol Mock\",\n responseURL: request.url,\n responseText: content,\n response: xhr.responseType === \"json\" ? rule?.body : content,\n getAllResponseHeaders: () => \"content-type: application/json\\r\\n\",\n getResponseHeader: (name: string) =>\n name.toLowerCase() === \"content-type\" ? \"application/json\" : null,\n };\n request.overrides = Object.keys(values);\n const ref = new WeakRef(xhr);\n mockRefs.add(ref);\n refsByRequest.set(xhr, ref);\n finalizer.register(xhr, ref, ref);\n for (const [key, value] of Object.entries(values))\n Object.defineProperty(xhr, key, { configurable: true, value });\n dispatch(\"readystatechange\");\n dispatch(offline ? \"error\" : \"load\");\n dispatch(\"loadend\");\n };\n const simulated = controls.offline || Boolean(rule);\n const latency = controls.latency + (rule?.delay ?? 0);\n if (!simulated && latency === 0) {\n try {\n return originalSend.call(xhr, body);\n } catch (error) {\n finish();\n throw error;\n }\n }\n const timer = setTimeout(() => {\n cleanups.delete(cancel);\n request.cancel = undefined;\n if (stopped) originalSend.call(xhr, body);\n else simulate();\n }, latency);\n const cancel = () => {\n clearTimeout(timer);\n cleanups.delete(cancel);\n request.cancel = undefined;\n if (stopped && !completed) {\n try {\n originalSend.call(xhr, body);\n } catch {}\n }\n };\n request.cancel = cancel;\n cleanups.add(cancel);\n dispatch(\"loadstart\");\n };\n const abort: typeof proto.abort = function (this: XMLHttpRequest) {\n const request = requests.get(this);\n if (request?.cancel) {\n request.cancel();\n this.dispatchEvent(new Event(\"abort\"));\n this.dispatchEvent(new Event(\"loadend\"));\n }\n return originalAbort.call(this);\n };\n proto.open = open;\n proto.send = send;\n proto.setRequestHeader = setHeader;\n proto.abort = abort;\n cleanups.add(() => {\n if (proto.open === open) proto.open = originalOpen;\n if (proto.send === send) proto.send = originalSend;\n if (proto.setRequestHeader === setHeader)\n proto.setRequestHeader = originalSetHeader;\n if (proto.abort === abort) proto.abort = originalAbort;\n });\n }\n return () => {\n stopped = true;\n for (const cleanup of [...cleanups]) {\n try {\n cleanup();\n } catch {}\n }\n cleanups.clear();\n };\n}\n","import {\n containsSerializationMarkers,\n isSensitiveKey,\n REDACTED,\n redactUrl,\n safeSerialize,\n} from \"./serialize\";\nimport { instrumentNetwork, type NetworkControls } from \"./network\";\nimport type {\n Command,\n DebugEvent,\n EventKind,\n FarolClient,\n FarolOptions,\n MockRule,\n QueryClientAdapter,\n Session,\n StoreAdapter,\n} from \"./types\";\nexport {\n containsSerializationMarkers,\n safeSerialize,\n redactUrl,\n REDACTED,\n} from \"./serialize\";\nexport type {\n FarolClient,\n FarolOptions,\n DebugEvent,\n EventKind,\n Session,\n StoreAdapter,\n QueryClientAdapter,\n MockRule,\n} from \"./types\";\nexport const SDK_VERSION = \"0.2.0\";\nconst SINGLETON = Symbol.for(\"aeres.farol.web.client\");\nconst NOOP = () => {};\nfunction inactive(): FarolClient {\n return {\n enabled: false,\n connected: false,\n session: null,\n getSession: () => null,\n track: NOOP,\n record: NOOP,\n watchStore: () => NOOP,\n observeQueryClient: () => NOOP,\n destroy: NOOP,\n };\n}\nconst uid = () =>\n globalThis.crypto?.randomUUID?.() ??\n `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`;\nconst clamp = (value: unknown, fallback: number, max: number) =>\n typeof value === \"number\" && Number.isFinite(value)\n ? Math.min(Math.max(Math.floor(value), 0), max)\n : fallback;\n/** Explicit development opt-in and local authenticated collector are both required. */\nexport function initFarol(options: FarolOptions): FarolClient {\n if (typeof window === \"undefined\" || typeof document === \"undefined\")\n return inactive();\n const win = window;\n const global = win as unknown as Record<symbol, FarolClient | undefined>;\n global[SINGLETON]?.destroy();\n if (\n options?.enabled !== true ||\n !options.token?.trim() ||\n typeof win.WebSocket !== \"function\"\n )\n return inactive();\n let endpoint: URL;\n try {\n endpoint = new URL(options.endpoint ?? \"ws://127.0.0.1:4318/ws\");\n } catch {\n return inactive();\n }\n if (\n ![\"ws:\", \"wss:\"].includes(endpoint.protocol) ||\n ![\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(endpoint.hostname) ||\n endpoint.username ||\n endpoint.password\n )\n return inactive();\n const session: Session = {\n platform: \"web\",\n runtime: \"browser\",\n id: uid(),\n appName: String(options.appName || \"React app\").slice(0, 120),\n url: redactUrl(win.location.href),\n userAgent: win.navigator.userAgent,\n startedAt: Date.now(),\n sdkVersion: SDK_VERSION,\n };\n const cleanups = new Set<() => void>();\n const stores = new Map<string, StoreAdapter<any>>();\n const queryClients = new Set<QueryClientAdapter>();\n const queue: string[] = [];\n const maxQueue = clamp(options.maxQueueSize, 400, 2_000);\n const controls: NetworkControls = {\n offline: false,\n latency: 0,\n mocks: new Map(),\n };\n let stopped = false;\n let ready = false;\n let socket: WebSocket | null = null;\n let reconnectTimer: ReturnType<typeof setTimeout> | undefined;\n let flushTimer: ReturnType<typeof setTimeout> | undefined;\n let attempt = 0;\n let highlighted: HTMLElement | null = null;\n let highlightTimer: ReturnType<typeof setTimeout> | undefined;\n let executingCommand = false;\n function flushQueue() {\n if (flushTimer) {\n clearTimeout(flushTimer);\n flushTimer = undefined;\n }\n if (stopped || !ready || socket?.readyState !== 1) return;\n while (queue.length && socket.bufferedAmount < 1_048_576) {\n try {\n socket.send(queue.shift()!);\n } catch {\n break;\n }\n }\n if (queue.length) flushTimer = setTimeout(flushQueue, 100);\n }\n function send(message: unknown, buffer = true) {\n if (stopped) return;\n let serialized = JSON.stringify(message);\n if (new TextEncoder().encode(serialized).byteLength > 65_536) {\n const result = message as {\n type?: string;\n id?: string;\n sessionId?: string;\n };\n if (result.type !== \"command.result\") return;\n serialized = JSON.stringify({\n type: \"command.result\",\n id: result.id,\n sessionId: result.sessionId,\n ok: false,\n error:\n \"Resultado excede o limite de 64 KiB após redação. Reduza o volume de dados consultados.\",\n });\n }\n if (\n ready &&\n socket?.readyState === 1 &&\n socket.bufferedAmount < 1_048_576\n ) {\n try {\n socket.send(serialized);\n return;\n } catch {\n /* enqueue for next connection */\n }\n }\n if (buffer && maxQueue > 0) {\n queue.push(serialized);\n if (queue.length > maxQueue) queue.splice(0, queue.length - maxQueue);\n if (ready && !flushTimer) flushTimer = setTimeout(flushQueue, 100);\n }\n }\n function record(\n kind: EventKind,\n name: string,\n data: Record<string, unknown>,\n level?: DebugEvent[\"level\"],\n ) {\n if (stopped) return;\n try {\n const safe = safeSerialize(data) as Record<string, unknown>;\n const event: DebugEvent = {\n id: uid(),\n sessionId: session.id,\n timestamp: Date.now(),\n kind,\n name: String(safeSerialize(name, { maxString: 200 })),\n data: safe,\n ...(level ? { level } : {}),\n ...(typeof data.duration === \"number\"\n ? { duration: data.duration }\n : {}),\n };\n if (new TextEncoder().encode(JSON.stringify(event)).byteLength > 60_000)\n event.data = {\n truncated: true,\n message: \"Event exceeded 60 KB after redaction\",\n };\n send({ type: \"event\", event });\n } catch {\n /* Debugging must never throw into application code. */\n }\n }\n const listen = (\n target: EventTarget,\n type: string,\n handler: EventListener,\n ) => {\n target.addEventListener(type, handler);\n cleanups.add(() => target.removeEventListener(type, handler));\n };\n function getStorage(area: unknown): Storage {\n if (area !== \"local\" && area !== \"session\")\n throw new Error(\"area must be local or session\");\n return area === \"local\" ? win.localStorage : win.sessionStorage;\n }\n function storageSnapshot(): {\n local: Record<string, unknown>;\n session: Record<string, unknown>;\n } {\n const result = {\n local: {} as Record<string, unknown>,\n session: {} as Record<string, unknown>,\n };\n for (const area of [\"local\", \"session\"] as const) {\n try {\n const storage = getStorage(area);\n for (let i = 0; i < Math.min(storage.length, 100); i++) {\n const key = storage.key(i);\n if (key != null)\n Object.defineProperty(result[area], key, {\n value: isSensitiveKey(key)\n ? REDACTED\n : safeSerialize(storage.getItem(key)),\n enumerable: true,\n });\n }\n } catch {\n result[area] = { unavailable: \"Storage is blocked by browser policy\" };\n }\n }\n return result;\n }\n function clearHighlight() {\n if (highlightTimer) clearTimeout(highlightTimer);\n highlighted?.remove();\n highlighted = null;\n }\n function domSnapshot() {\n return Array.from(\n document.body?.querySelectorAll(\n \"main,section,article,header,nav,h1,h2,h3,p,button,a,input,select,textarea,[role]\",\n ) ?? [],\n )\n .filter((element) => element !== highlighted)\n .slice(0, 150)\n .map((element) => ({\n tag: element.tagName.toLowerCase(),\n id: element.id,\n role: element.getAttribute(\"role\"),\n // Text excludes controls and editable/private content; no input values or data-* attributes.\n text:\n element.matches(\n \"input,select,textarea,[contenteditable], [data-farol-private], [data-private]\",\n ) ||\n element.closest(\n \"[data-farol-private],[data-private],[contenteditable]\",\n )\n ? \"[private]\"\n : Array.from(element.childNodes)\n .filter((node) => node.nodeType === 3)\n .map((node) => node.textContent)\n .join(\" \")\n .trim()\n .slice(0, 160),\n rect: (() => {\n const rect = element.getBoundingClientRect();\n return {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n })(),\n }));\n }\n async function execute(command: Command): Promise<unknown> {\n const args = command.args ?? {};\n switch (command.name) {\n case \"storage.list\":\n return storageSnapshot();\n case \"storage.set\": {\n if (\n typeof args.key !== \"string\" ||\n typeof args.value !== \"string\" ||\n args.key.length > 512 ||\n args.value.length > 16_384\n )\n throw new Error(\"Invalid storage key/value\");\n if (containsSerializationMarkers(args.value))\n throw new Error(\n \"Valor contém marcadores de redação ou truncamento. Informe um valor completo para evitar sobrescrever dados reais.\",\n );\n getStorage(args.area).setItem(args.key, args.value);\n return { area: args.area, key: args.key, updated: true };\n }\n case \"storage.remove\": {\n if (typeof args.key !== \"string\")\n throw new Error(\"Invalid storage key\");\n getStorage(args.area).removeItem(args.key);\n return { area: args.area, key: args.key, removed: true };\n }\n case \"state.set\": {\n const store = stores.get(String(args.store));\n if (!store?.setState) throw new Error(\"Store does not expose setState\");\n if (containsSerializationMarkers(args.value))\n throw new Error(\n \"Estado contém marcadores de redação ou truncamento. Snapshots incompletos não podem substituir dados reais.\",\n );\n store.setState(args.value);\n return { store: args.store, state: store.getState() };\n }\n case \"query.invalidate\": {\n if (args.queryKey !== undefined && !Array.isArray(args.queryKey))\n throw new Error(\"queryKey must be an array\");\n if (!queryClients.size) throw new Error(\"No QueryClient registered\");\n await Promise.all(\n [...queryClients].map((client) =>\n Promise.resolve(\n client.invalidateQueries(\n args.queryKey\n ? { queryKey: args.queryKey as unknown[] }\n : undefined,\n ),\n ),\n ),\n );\n return { invalidated: true };\n }\n case \"network.get\":\n return {\n offline: controls.offline,\n latency: controls.latency,\n mocks: [...controls.mocks.values()],\n };\n case \"network.configure\": {\n if (typeof args.offline === \"boolean\") controls.offline = args.offline;\n if (args.latency !== undefined)\n controls.latency = clamp(args.latency, 0, 30_000);\n record(\"custom\", \"Network simulation configured\", {\n ...controls,\n mocks: controls.mocks.size,\n });\n return { offline: controls.offline, latency: controls.latency };\n }\n case \"mock.set\": {\n if (\n typeof args.id !== \"string\" ||\n !args.id ||\n typeof args.url !== \"string\" ||\n !args.url ||\n args.url.length > 512 ||\n typeof args.method !== \"string\"\n )\n throw new Error(\"Mock requires id, url and method\");\n const status = Number(args.status ?? 200);\n if (!Number.isInteger(status) || status < 200 || status > 599)\n throw new Error(\"Mock status must be between 200 and 599\");\n if (controls.mocks.size >= 50 && !controls.mocks.has(args.id))\n throw new Error(\"Maximum 50 mocks\");\n const rule: MockRule = {\n id: args.id.slice(0, 100),\n url: args.url,\n method: args.method.toUpperCase(),\n status,\n body: args.body,\n delay: clamp(args.delay, 0, 30_000),\n };\n controls.mocks.set(rule.id, rule);\n return rule;\n }\n case \"mock.remove\":\n return { removed: controls.mocks.delete(String(args.id)) };\n case \"dom.snapshot\":\n return { elements: domSnapshot() };\n case \"dom.highlight\": {\n if (typeof args.selector !== \"string\" || args.selector.length > 512)\n throw new Error(\"Invalid selector\");\n const target = document.querySelector(args.selector);\n if (!target) throw new Error(\"Element not found\");\n clearHighlight();\n const rect = target.getBoundingClientRect();\n highlighted = document.createElement(\"div\");\n highlighted.setAttribute(\"data-farol-highlight\", \"\");\n highlighted.style.cssText = `position:fixed;pointer-events:none;z-index:2147483647;border:2px solid #27c9a8;background:rgba(39,201,168,.12);left:${rect.left}px;top:${rect.top}px;width:${rect.width}px;height:${rect.height}px;box-sizing:border-box;`;\n document.body.appendChild(highlighted);\n highlightTimer = setTimeout(clearHighlight, 3_000);\n return { highlighted: args.selector };\n }\n case \"page.reload\":\n setTimeout(() => {\n if (!stopped) win.location.reload();\n }, 80);\n return { reloading: true };\n case \"nav.go\": {\n if (typeof args.url !== \"string\") throw new Error(\"Invalid URL\");\n const url = new URL(args.url, win.location.href);\n if (\n url.origin !== win.location.origin ||\n ![\"http:\", \"https:\"].includes(url.protocol) ||\n url.username ||\n url.password\n )\n throw new Error(\"Navigation must stay on the same origin\");\n win.history.pushState(null, \"\", url.href);\n win.dispatchEvent(new PopStateEvent(\"popstate\"));\n return { url: redactUrl(url.href) };\n }\n default:\n throw new Error(`Unsupported command: ${command.name}`);\n }\n }\n function connect() {\n if (stopped) return;\n try {\n socket = new win.WebSocket(endpoint.href);\n } catch {\n scheduleReconnect();\n return;\n }\n const current = socket;\n current.onopen = () => {\n if (stopped) return;\n current.send(\n JSON.stringify({ type: \"auth\", role: \"sdk\", token: options.token }),\n );\n };\n current.onmessage = (message) => {\n if (\n stopped ||\n current !== socket ||\n typeof message.data !== \"string\" ||\n message.data.length > 65_536\n )\n return;\n try {\n const data = JSON.parse(message.data);\n if (data.type === \"ready\") {\n ready = true;\n attempt = 0;\n send({ type: \"hello\", session });\n flushQueue();\n return;\n }\n if (\n data.type !== \"command\" ||\n !ready ||\n data.sessionId !== session.id ||\n typeof data.id !== \"string\" ||\n data.id.length > 128 ||\n typeof data.name !== \"string\" ||\n data.name.length > 100\n )\n return;\n if (executingCommand) {\n send(\n {\n type: \"command.result\",\n id: data.id,\n sessionId: session.id,\n ok: false,\n error: \"Another command is running\",\n },\n false,\n );\n return;\n }\n executingCommand = true;\n void execute(data as Command)\n .then(\n (result) => {\n send(\n {\n type: \"command.result\",\n id: data.id,\n sessionId: session.id,\n ok: true,\n data: safeSerialize(result),\n },\n false,\n );\n },\n (error) => {\n send(\n {\n type: \"command.result\",\n id: data.id,\n sessionId: session.id,\n ok: false,\n error: String(\n safeSerialize(\n error instanceof Error ? error.message : String(error),\n ),\n ),\n },\n false,\n );\n },\n )\n .finally(() => {\n executingCommand = false;\n });\n } catch {\n /* Ignore malformed messages. */\n }\n };\n current.onclose = (event) => {\n if (current !== socket) return;\n ready = false;\n if (!stopped && event.code !== 1008) scheduleReconnect();\n };\n current.onerror = NOOP;\n }\n function scheduleReconnect() {\n if (stopped || reconnectTimer) return;\n reconnectTimer = setTimeout(\n () => {\n reconnectTimer = undefined;\n connect();\n },\n Math.min(500 * 2 ** attempt++, 15_000) + Math.random() * 250,\n );\n }\n const client: FarolClient = {\n enabled: true,\n get connected() {\n return ready && !stopped;\n },\n session,\n getSession: () => session,\n record,\n track: (name, data = {}) => record(\"custom\", name, data),\n watchStore<T>(name: string, adapter: StoreAdapter<T>) {\n if (stopped) return NOOP;\n const key = String(name).slice(0, 120);\n stores.set(key, adapter);\n const emit = () => {\n try {\n record(\"state\", key, { store: key, state: adapter.getState() });\n } catch (error) {\n record(\"error\", \"Store inspection failed\", { store: key, error });\n }\n };\n emit();\n let unsubscribe: (() => void) | undefined;\n try {\n unsubscribe = adapter.subscribe(emit);\n } catch (error) {\n record(\"error\", \"Store subscription failed\", { store: key, error });\n }\n const cleanup = () => {\n try {\n unsubscribe?.();\n } catch {}\n if (stores.get(key) === adapter) stores.delete(key);\n cleanups.delete(cleanup);\n };\n cleanups.add(cleanup);\n return cleanup;\n },\n observeQueryClient(queryClient: QueryClientAdapter) {\n if (stopped) return NOOP;\n queryClients.add(queryClient);\n const emit = (query: { queryKey: readonly unknown[]; state: unknown }) =>\n record(\"query\", \"Query cache\", {\n queryKey: query.queryKey,\n state: query.state,\n });\n let unsubscribe: (() => void) | undefined;\n try {\n const cache = queryClient.getQueryCache();\n cache.getAll().slice(0, 100).forEach(emit);\n unsubscribe = cache.subscribe((event) => {\n if (event?.query) emit(event.query);\n });\n } catch (error) {\n record(\"error\", \"Query inspection failed\", { error });\n }\n const cleanup = () => {\n try {\n unsubscribe?.();\n } catch {}\n queryClients.delete(queryClient);\n cleanups.delete(cleanup);\n };\n cleanups.add(cleanup);\n return cleanup;\n },\n destroy() {\n if (stopped) return;\n stopped = true;\n ready = false;\n if (reconnectTimer) clearTimeout(reconnectTimer);\n if (flushTimer) clearTimeout(flushTimer);\n clearHighlight();\n for (const cleanup of [...cleanups]) {\n try {\n cleanup();\n } catch {}\n }\n cleanups.clear();\n stores.clear();\n queryClients.clear();\n controls.mocks.clear();\n queue.length = 0;\n if (socket) {\n socket.onopen =\n socket.onmessage =\n socket.onclose =\n socket.onerror =\n null;\n socket.close(1000, \"Farol stopped\");\n socket = null;\n }\n if (global[SINGLETON] === client) delete global[SINGLETON];\n },\n };\n global[SINGLETON] = client;\n\n for (const level of [\"debug\", \"log\", \"info\", \"warn\", \"error\"] as const) {\n const original = win.console[level];\n const wrapped = (...args: unknown[]) => {\n original.apply(win.console, args);\n record(\"console\", level, { args }, level === \"log\" ? \"info\" : level);\n };\n win.console[level] = wrapped;\n cleanups.add(() => {\n if (win.console[level] === wrapped) win.console[level] = original;\n });\n }\n listen(win, \"error\", ((event: ErrorEvent) =>\n record(\n \"error\",\n event.message || \"Resource error\",\n {\n error: event.error,\n message: event.message,\n filename: event.filename,\n line: event.lineno,\n column: event.colno,\n },\n \"error\",\n )) as EventListener);\n listen(win, \"unhandledrejection\", ((event: PromiseRejectionEvent) =>\n record(\n \"error\",\n \"Unhandled promise rejection\",\n { reason: event.reason },\n \"error\",\n )) as EventListener);\n try {\n cleanups.add(\n instrumentNetwork({\n win,\n endpoint: endpoint.href,\n controls,\n captureBodies: options.captureBodies === true,\n maxBodyBytes: clamp(options.maxBodyBytes, 8_192, 32_768),\n emit: (data) =>\n record(\n \"network\",\n `${data.method} ${redactUrl(String(data.url))}`,\n data,\n data.error || Number(data.status) >= 400 ? \"error\" : \"info\",\n ),\n }),\n );\n } catch (error) {\n record(\"error\", \"Network instrumentation unavailable\", { error });\n }\n\n try {\n const prototype = win.Storage.prototype;\n for (const operation of [\"setItem\", \"removeItem\", \"clear\"] as const) {\n const original = prototype[operation];\n const wrapped = function (this: Storage, ...args: string[]) {\n const result = (original as Function).apply(this, args);\n let area: \"local\" | \"session\" | undefined;\n try {\n area =\n this === win.localStorage\n ? \"local\"\n : this === win.sessionStorage\n ? \"session\"\n : undefined;\n } catch {}\n if (area)\n record(\"storage\", `${area}.${operation}`, {\n area,\n key: args[0] ?? null,\n value: args[0] && isSensitiveKey(args[0]) ? REDACTED : args[1],\n action: operation,\n });\n return result;\n };\n (prototype as unknown as Record<string, Function>)[operation] = wrapped;\n cleanups.add(() => {\n if (prototype[operation] === wrapped)\n (prototype as unknown as Record<string, Function>)[operation] =\n original;\n });\n }\n listen(win, \"storage\", ((event: StorageEvent) => {\n let area = \"local\";\n try {\n if (event.storageArea === win.sessionStorage) area = \"session\";\n } catch {}\n record(\"storage\", \"Cross-tab storage change\", {\n area,\n key: event.key,\n value:\n event.key && isSensitiveKey(event.key) ? REDACTED : event.newValue,\n action:\n event.key == null\n ? \"clear\"\n : event.newValue == null\n ? \"removeItem\"\n : \"setItem\",\n });\n }) as EventListener);\n record(\"storage\", \"Storage snapshot\", storageSnapshot());\n } catch (error) {\n record(\"storage\", \"Storage unavailable\", { error });\n }\n\n const navigation = (action: string) =>\n record(\"navigation\", action, {\n url: redactUrl(win.location.href),\n title: document.title,\n });\n for (const method of [\"pushState\", \"replaceState\"] as const) {\n const original = win.history[method];\n const wrapped: typeof original = function (...args) {\n const result = original.apply(win.history, args);\n navigation(method);\n return result;\n };\n win.history[method] = wrapped;\n cleanups.add(() => {\n if (win.history[method] === wrapped) win.history[method] = original;\n });\n }\n listen(win, \"popstate\", () => navigation(\"popstate\"));\n listen(win, \"hashchange\", () => navigation(\"hashchange\"));\n navigation(\"initial\");\n if (typeof win.PerformanceObserver === \"function\") {\n let cls = 0;\n let windowStart = 0;\n let lastShift = 0;\n let windowValue = 0;\n for (const type of [\n \"navigation\",\n \"largest-contentful-paint\",\n \"layout-shift\",\n \"longtask\",\n \"paint\",\n ]) {\n if (!win.PerformanceObserver.supportedEntryTypes?.includes(type))\n continue;\n try {\n const observer = new win.PerformanceObserver((list) => {\n for (const entry of list.getEntries().slice(0, 50)) {\n const item = entry as PerformanceEntry & {\n hadRecentInput?: boolean;\n value?: number;\n renderTime?: number;\n loadTime?: number;\n domContentLoadedEventEnd?: number;\n loadEventEnd?: number;\n responseStart?: number;\n transferSize?: number;\n };\n if (type === \"layout-shift\") {\n if (item.hadRecentInput) continue;\n if (\n !lastShift ||\n item.startTime - lastShift > 1_000 ||\n item.startTime - windowStart > 5_000\n ) {\n windowStart = item.startTime;\n windowValue = 0;\n }\n windowValue += item.value ?? 0;\n lastShift = item.startTime;\n cls = Math.max(cls, windowValue);\n record(\"performance\", \"CLS\", {\n value: cls,\n delta: item.value,\n startTime: item.startTime,\n });\n } else\n record(\n \"performance\",\n type === \"largest-contentful-paint\" ? \"LCP\" : type,\n {\n value:\n type === \"largest-contentful-paint\"\n ? item.renderTime || item.loadTime || item.startTime\n : item.duration || item.startTime,\n name: item.name,\n duration: item.duration,\n startTime: item.startTime,\n ...(type === \"navigation\"\n ? {\n domContentLoaded: item.domContentLoadedEventEnd,\n load: item.loadEventEnd,\n ttfb: item.responseStart,\n transferSize: item.transferSize,\n }\n : {}),\n },\n );\n }\n });\n observer.observe({ type, buffered: true });\n cleanups.add(() => observer.disconnect());\n } catch {\n /* Entry support varies by browser. */\n }\n }\n }\n connect();\n return client;\n}\n"],"names":["value","requestBody","responseBody","client"],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { MockRule } from "./types";
2
+ export interface NetworkControls {
3
+ offline: boolean;
4
+ latency: number;
5
+ mocks: Map<string, MockRule>;
6
+ }
7
+ interface NetworkContext {
8
+ win: Window & typeof globalThis;
9
+ endpoint: string;
10
+ controls: NetworkControls;
11
+ captureBodies: boolean;
12
+ maxBodyBytes: number;
13
+ emit(data: Record<string, unknown>): void;
14
+ }
15
+ export declare function matchMock(rules: Map<string, MockRule>, url: string, method: string): MockRule | undefined;
16
+ /** Every wrapper delegates native semantics unless an explicit debug simulation is active. */
17
+ export declare function instrumentNetwork(ctx: NetworkContext): () => void;
18
+ export {};
package/dist/react.cjs ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ function createProfilerCallback(client) {
6
+ return (id, phase, actualDuration, baseDuration, startTime, commitTime) => client.record("render", id, {
7
+ id,
8
+ phase,
9
+ actualDuration,
10
+ baseDuration,
11
+ startTime,
12
+ commitTime
13
+ });
14
+ }
15
+ function FarolProfiler({
16
+ client,
17
+ id,
18
+ children
19
+ }) {
20
+ return /* @__PURE__ */ jsxRuntime.jsx(react.Profiler, { id, onRender: createProfilerCallback(client), children });
21
+ }
22
+ class FarolErrorBoundary extends react.Component {
23
+ state = { error: null };
24
+ static getDerivedStateFromError(error) {
25
+ return { error };
26
+ }
27
+ componentDidCatch(error, info) {
28
+ this.props.client.record(
29
+ "error",
30
+ "React error boundary",
31
+ { error, componentStack: info.componentStack },
32
+ "error"
33
+ );
34
+ }
35
+ reset = () => this.setState({ error: null });
36
+ render() {
37
+ if (!this.state.error) return this.props.children;
38
+ if (typeof this.props.fallback === "function")
39
+ return this.props.fallback(this.state.error, this.reset);
40
+ return this.props.fallback ?? /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", children: [
41
+ "Ocorreu um erro nesta parte do aplicativo.",
42
+ " ",
43
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: this.reset, children: "Tentar novamente" })
44
+ ] });
45
+ }
46
+ }
47
+ function useFarolTrack(client, name, data) {
48
+ react.useEffect(() => {
49
+ client.track(name, data);
50
+ }, [client, name, data]);
51
+ }
52
+ exports.FarolErrorBoundary = FarolErrorBoundary;
53
+ exports.FarolProfiler = FarolProfiler;
54
+ exports.createProfilerCallback = createProfilerCallback;
55
+ exports.useFarolTrack = useFarolTrack;
56
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.cjs","sources":["../src/react.tsx"],"sourcesContent":["import {\n Component,\n Profiler,\n useEffect,\n type ErrorInfo,\n type ProfilerOnRenderCallback,\n type ReactNode,\n} from \"react\";\nimport type { FarolClient } from \"./types\";\nexport function createProfilerCallback(\n client: FarolClient,\n): ProfilerOnRenderCallback {\n return (id, phase, actualDuration, baseDuration, startTime, commitTime) =>\n client.record(\"render\", id, {\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n });\n}\nexport function FarolProfiler({\n client,\n id,\n children,\n}: {\n client: FarolClient;\n id: string;\n children: ReactNode;\n}) {\n return (\n <Profiler id={id} onRender={createProfilerCallback(client)}>\n {children}\n </Profiler>\n );\n}\ninterface BoundaryProps {\n client: FarolClient;\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n}\ninterface BoundaryState {\n error: Error | null;\n}\nexport class FarolErrorBoundary extends Component<\n BoundaryProps,\n BoundaryState\n> {\n state: BoundaryState = { error: null };\n static getDerivedStateFromError(error: Error): BoundaryState {\n return { error };\n }\n componentDidCatch(error: Error, info: ErrorInfo) {\n this.props.client.record(\n \"error\",\n \"React error boundary\",\n { error, componentStack: info.componentStack },\n \"error\",\n );\n }\n reset = () => this.setState({ error: null });\n render() {\n if (!this.state.error) return this.props.children;\n if (typeof this.props.fallback === \"function\")\n return this.props.fallback(this.state.error, this.reset);\n return (\n this.props.fallback ?? (\n <div role=\"alert\">\n Ocorreu um erro nesta parte do aplicativo.{\" \"}\n <button type=\"button\" onClick={this.reset}>\n Tentar novamente\n </button>\n </div>\n )\n );\n }\n}\n/** Emits when the name or payload identity changes. Memoize data for mount-only events. */\nexport function useFarolTrack(\n client: FarolClient,\n name: string,\n data?: Record<string, unknown>,\n) {\n useEffect(() => {\n client.track(name, data);\n }, [client, name, data]);\n}\n"],"names":["Profiler","Component","jsxs","useEffect"],"mappings":";;;;AASO,SAAS,uBACd,QAC0B;AAC1B,SAAO,CAAC,IAAI,OAAO,gBAAgB,cAAc,WAAW,eAC1D,OAAO,OAAO,UAAU,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AACL;AACO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,wCACGA,MAAAA,UAAA,EAAS,IAAQ,UAAU,uBAAuB,MAAM,GACtD,UACH;AAEJ;AASO,MAAM,2BAA2BC,MAAAA,UAGtC;AAAA,EACA,QAAuB,EAAE,OAAO,KAAA;AAAA,EAChC,OAAO,yBAAyB,OAA6B;AAC3D,WAAO,EAAE,MAAA;AAAA,EACX;AAAA,EACA,kBAAkB,OAAc,MAAiB;AAC/C,SAAK,MAAM,OAAO;AAAA,MAChB;AAAA,MACA;AAAA,MACA,EAAE,OAAO,gBAAgB,KAAK,eAAA;AAAA,MAC9B;AAAA,IAAA;AAAA,EAEJ;AAAA,EACA,QAAQ,MAAM,KAAK,SAAS,EAAE,OAAO,MAAM;AAAA,EAC3C,SAAS;AACP,QAAI,CAAC,KAAK,MAAM,MAAO,QAAO,KAAK,MAAM;AACzC,QAAI,OAAO,KAAK,MAAM,aAAa;AACjC,aAAO,KAAK,MAAM,SAAS,KAAK,MAAM,OAAO,KAAK,KAAK;AACzD,WACE,KAAK,MAAM,YACTC,2BAAAA,KAAC,OAAA,EAAI,MAAK,SAAQ,UAAA;AAAA,MAAA;AAAA,MAC2B;AAAA,qCAC1C,UAAA,EAAO,MAAK,UAAS,SAAS,KAAK,OAAO,UAAA,mBAAA,CAE3C;AAAA,IAAA,GACF;AAAA,EAGN;AACF;AAEO,SAAS,cACd,QACA,MACA,MACA;AACAC,QAAAA,UAAU,MAAM;AACd,WAAO,MAAM,MAAM,IAAI;AAAA,EACzB,GAAG,CAAC,QAAQ,MAAM,IAAI,CAAC;AACzB;;;;;"}
@@ -0,0 +1,26 @@
1
+ import { Component, type ErrorInfo, type ProfilerOnRenderCallback, type ReactNode } from "react";
2
+ import type { FarolClient } from "./types";
3
+ export declare function createProfilerCallback(client: FarolClient): ProfilerOnRenderCallback;
4
+ export declare function FarolProfiler({ client, id, children, }: {
5
+ client: FarolClient;
6
+ id: string;
7
+ children: ReactNode;
8
+ }): import("react").JSX.Element;
9
+ interface BoundaryProps {
10
+ client: FarolClient;
11
+ children: ReactNode;
12
+ fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);
13
+ }
14
+ interface BoundaryState {
15
+ error: Error | null;
16
+ }
17
+ export declare class FarolErrorBoundary extends Component<BoundaryProps, BoundaryState> {
18
+ state: BoundaryState;
19
+ static getDerivedStateFromError(error: Error): BoundaryState;
20
+ componentDidCatch(error: Error, info: ErrorInfo): void;
21
+ reset: () => void;
22
+ render(): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | import("react").ReactPortal | import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | import("react").JSX.Element | null | undefined;
23
+ }
24
+ /** Emits when the name or payload identity changes. Memoize data for mount-only events. */
25
+ export declare function useFarolTrack(client: FarolClient, name: string, data?: Record<string, unknown>): void;
26
+ export {};
package/dist/react.js ADDED
@@ -0,0 +1,56 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { Component, Profiler, useEffect } from "react";
3
+ function createProfilerCallback(client) {
4
+ return (id, phase, actualDuration, baseDuration, startTime, commitTime) => client.record("render", id, {
5
+ id,
6
+ phase,
7
+ actualDuration,
8
+ baseDuration,
9
+ startTime,
10
+ commitTime
11
+ });
12
+ }
13
+ function FarolProfiler({
14
+ client,
15
+ id,
16
+ children
17
+ }) {
18
+ return /* @__PURE__ */ jsx(Profiler, { id, onRender: createProfilerCallback(client), children });
19
+ }
20
+ class FarolErrorBoundary extends Component {
21
+ state = { error: null };
22
+ static getDerivedStateFromError(error) {
23
+ return { error };
24
+ }
25
+ componentDidCatch(error, info) {
26
+ this.props.client.record(
27
+ "error",
28
+ "React error boundary",
29
+ { error, componentStack: info.componentStack },
30
+ "error"
31
+ );
32
+ }
33
+ reset = () => this.setState({ error: null });
34
+ render() {
35
+ if (!this.state.error) return this.props.children;
36
+ if (typeof this.props.fallback === "function")
37
+ return this.props.fallback(this.state.error, this.reset);
38
+ return this.props.fallback ?? /* @__PURE__ */ jsxs("div", { role: "alert", children: [
39
+ "Ocorreu um erro nesta parte do aplicativo.",
40
+ " ",
41
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: this.reset, children: "Tentar novamente" })
42
+ ] });
43
+ }
44
+ }
45
+ function useFarolTrack(client, name, data) {
46
+ useEffect(() => {
47
+ client.track(name, data);
48
+ }, [client, name, data]);
49
+ }
50
+ export {
51
+ FarolErrorBoundary,
52
+ FarolProfiler,
53
+ createProfilerCallback,
54
+ useFarolTrack
55
+ };
56
+ //# sourceMappingURL=react.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"react.js","sources":["../src/react.tsx"],"sourcesContent":["import {\n Component,\n Profiler,\n useEffect,\n type ErrorInfo,\n type ProfilerOnRenderCallback,\n type ReactNode,\n} from \"react\";\nimport type { FarolClient } from \"./types\";\nexport function createProfilerCallback(\n client: FarolClient,\n): ProfilerOnRenderCallback {\n return (id, phase, actualDuration, baseDuration, startTime, commitTime) =>\n client.record(\"render\", id, {\n id,\n phase,\n actualDuration,\n baseDuration,\n startTime,\n commitTime,\n });\n}\nexport function FarolProfiler({\n client,\n id,\n children,\n}: {\n client: FarolClient;\n id: string;\n children: ReactNode;\n}) {\n return (\n <Profiler id={id} onRender={createProfilerCallback(client)}>\n {children}\n </Profiler>\n );\n}\ninterface BoundaryProps {\n client: FarolClient;\n children: ReactNode;\n fallback?: ReactNode | ((error: Error, reset: () => void) => ReactNode);\n}\ninterface BoundaryState {\n error: Error | null;\n}\nexport class FarolErrorBoundary extends Component<\n BoundaryProps,\n BoundaryState\n> {\n state: BoundaryState = { error: null };\n static getDerivedStateFromError(error: Error): BoundaryState {\n return { error };\n }\n componentDidCatch(error: Error, info: ErrorInfo) {\n this.props.client.record(\n \"error\",\n \"React error boundary\",\n { error, componentStack: info.componentStack },\n \"error\",\n );\n }\n reset = () => this.setState({ error: null });\n render() {\n if (!this.state.error) return this.props.children;\n if (typeof this.props.fallback === \"function\")\n return this.props.fallback(this.state.error, this.reset);\n return (\n this.props.fallback ?? (\n <div role=\"alert\">\n Ocorreu um erro nesta parte do aplicativo.{\" \"}\n <button type=\"button\" onClick={this.reset}>\n Tentar novamente\n </button>\n </div>\n )\n );\n }\n}\n/** Emits when the name or payload identity changes. Memoize data for mount-only events. */\nexport function useFarolTrack(\n client: FarolClient,\n name: string,\n data?: Record<string, unknown>,\n) {\n useEffect(() => {\n client.track(name, data);\n }, [client, name, data]);\n}\n"],"names":[],"mappings":";;AASO,SAAS,uBACd,QAC0B;AAC1B,SAAO,CAAC,IAAI,OAAO,gBAAgB,cAAc,WAAW,eAC1D,OAAO,OAAO,UAAU,IAAI;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,CACD;AACL;AACO,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,6BACG,UAAA,EAAS,IAAQ,UAAU,uBAAuB,MAAM,GACtD,UACH;AAEJ;AASO,MAAM,2BAA2B,UAGtC;AAAA,EACA,QAAuB,EAAE,OAAO,KAAA;AAAA,EAChC,OAAO,yBAAyB,OAA6B;AAC3D,WAAO,EAAE,MAAA;AAAA,EACX;AAAA,EACA,kBAAkB,OAAc,MAAiB;AAC/C,SAAK,MAAM,OAAO;AAAA,MAChB;AAAA,MACA;AAAA,MACA,EAAE,OAAO,gBAAgB,KAAK,eAAA;AAAA,MAC9B;AAAA,IAAA;AAAA,EAEJ;AAAA,EACA,QAAQ,MAAM,KAAK,SAAS,EAAE,OAAO,MAAM;AAAA,EAC3C,SAAS;AACP,QAAI,CAAC,KAAK,MAAM,MAAO,QAAO,KAAK,MAAM;AACzC,QAAI,OAAO,KAAK,MAAM,aAAa;AACjC,aAAO,KAAK,MAAM,SAAS,KAAK,MAAM,OAAO,KAAK,KAAK;AACzD,WACE,KAAK,MAAM,YACT,qBAAC,OAAA,EAAI,MAAK,SAAQ,UAAA;AAAA,MAAA;AAAA,MAC2B;AAAA,0BAC1C,UAAA,EAAO,MAAK,UAAS,SAAS,KAAK,OAAO,UAAA,mBAAA,CAE3C;AAAA,IAAA,GACF;AAAA,EAGN;AACF;AAEO,SAAS,cACd,QACA,MACA,MACA;AACA,YAAU,MAAM;AACd,WAAO,MAAM,MAAM,IAAI;AAAA,EACzB,GAAG,CAAC,QAAQ,MAAM,IAAI,CAAC;AACzB;"}
@@ -0,0 +1,13 @@
1
+ /** Redaction happens before queuing, persistence, or transmission. */
2
+ export declare const REDACTED = "[REDACTED]";
3
+ export declare const isSensitiveKey: (key: string) => boolean;
4
+ export declare function redactUrl(value: string): string;
5
+ export interface SerializeLimits {
6
+ maxDepth?: number;
7
+ maxEntries?: number;
8
+ maxString?: number;
9
+ }
10
+ /** Serializable, bounded, circular-safe data. Does not invoke user getters or toJSON. */
11
+ export declare function safeSerialize(value: unknown, limits?: SerializeLimits): unknown;
12
+ /** Conservative guard for values copied from a lossy/redacted snapshot, including encoded JSON/URLs. */
13
+ export declare function containsSerializationMarkers(value: unknown): boolean;
@@ -0,0 +1,77 @@
1
+ export type EventKind = "console" | "network" | "error" | "storage" | "state" | "query" | "navigation" | "performance" | "render" | "custom" | "dom";
2
+ export interface DebugEvent {
3
+ id: string;
4
+ sessionId: string;
5
+ timestamp: number;
6
+ kind: EventKind;
7
+ name: string;
8
+ level?: "debug" | "info" | "warn" | "error";
9
+ duration?: number;
10
+ data: Record<string, unknown>;
11
+ }
12
+ export interface Session {
13
+ platform?: "web";
14
+ runtime?: "browser";
15
+ id: string;
16
+ appName: string;
17
+ url: string;
18
+ userAgent: string;
19
+ startedAt: number;
20
+ sdkVersion: string;
21
+ }
22
+ export interface FarolOptions {
23
+ appName: string;
24
+ /** Must be explicitly true. Use import.meta.env.DEV or process.env.NODE_ENV === 'development'. */
25
+ enabled?: boolean;
26
+ /** Local collector only. Defaults to ws://127.0.0.1:4318/ws. */
27
+ endpoint?: string;
28
+ /** Pairing token displayed by the local collector. */
29
+ token?: string;
30
+ /** Sensitive data is redacted, but request/response bodies are still opt-in. */
31
+ captureBodies?: boolean;
32
+ maxBodyBytes?: number;
33
+ maxQueueSize?: number;
34
+ }
35
+ export interface StoreAdapter<T = unknown> {
36
+ getState(): T;
37
+ subscribe(listener: (...args: any[]) => void): () => void;
38
+ setState?: (state: T) => void;
39
+ }
40
+ export interface QueryClientAdapter {
41
+ getQueryCache(): {
42
+ getAll(): Array<{
43
+ queryKey: readonly unknown[];
44
+ state: unknown;
45
+ }>;
46
+ subscribe(listener: (event: any) => void): () => void;
47
+ };
48
+ invalidateQueries(filters?: {
49
+ queryKey?: readonly unknown[];
50
+ }): unknown;
51
+ }
52
+ export interface FarolClient {
53
+ readonly enabled: boolean;
54
+ readonly connected: boolean;
55
+ readonly session: Session | null;
56
+ getSession(): Session | null;
57
+ track(name: string, data?: Record<string, unknown>): void;
58
+ record(kind: EventKind, name: string, data: Record<string, unknown>, level?: DebugEvent["level"]): void;
59
+ watchStore<T>(name: string, adapter: StoreAdapter<T>): () => void;
60
+ observeQueryClient(client: QueryClientAdapter): () => void;
61
+ destroy(): void;
62
+ }
63
+ export interface MockRule {
64
+ id: string;
65
+ url: string;
66
+ method: string;
67
+ status: number;
68
+ body: unknown;
69
+ delay?: number;
70
+ }
71
+ export interface Command {
72
+ type: "command";
73
+ id: string;
74
+ sessionId: string;
75
+ name: string;
76
+ args: Record<string, unknown>;
77
+ }
package/package.json CHANGED
@@ -1,6 +1,56 @@
1
1
  {
2
2
  "name": "@aeres/farol-web",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.2.0",
4
+ "description": "Development-only browser observability SDK for Farol Web",
5
+ "type": "module",
6
+ "files": [
7
+ "dist",
8
+ "README.md"
9
+ ],
10
+ "main": "./dist/index.cjs",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "require": "./dist/index.cjs"
18
+ },
19
+ "./react": {
20
+ "types": "./dist/react.d.ts",
21
+ "import": "./dist/react.js",
22
+ "require": "./dist/react.cjs"
23
+ }
24
+ },
25
+ "sideEffects": false,
26
+ "scripts": {
27
+ "build": "vite build && tsc -p tsconfig.build.json",
28
+ "test": "node --import tsx --test test/*.test.ts",
29
+ "prepublishOnly": "npm run build && npm test"
30
+ },
31
+ "peerDependencies": {
32
+ "react": ">=18.0.0"
33
+ },
34
+ "peerDependenciesMeta": {
35
+ "react": {
36
+ "optional": true
37
+ }
38
+ },
39
+ "license": "UNLICENSED",
40
+ "publishConfig": {
41
+ "registry": "https://registry.npmjs.org/",
42
+ "access": "public"
43
+ },
44
+ "keywords": [
45
+ "farol",
46
+ "react",
47
+ "debugging",
48
+ "development",
49
+ "observability"
50
+ ],
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "git+https://github.com/aeresdigital/aeres_farol_dev_tools.git",
54
+ "directory": "packages/sdk"
55
+ }
56
+ }