@uncaughtdev/core 0.1.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.
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/dist/chunk-E76GW6KF.js +2 -0
- package/dist/chunk-E76GW6KF.js.map +1 -0
- package/dist/chunk-FFHQ452Q.js +2 -0
- package/dist/chunk-FFHQ452Q.js.map +1 -0
- package/dist/chunk-JALIO2BZ.mjs +2 -0
- package/dist/chunk-JALIO2BZ.mjs.map +1 -0
- package/dist/chunk-P6JRN5CN.mjs +2 -0
- package/dist/chunk-P6JRN5CN.mjs.map +1 -0
- package/dist/index.d.mts +155 -0
- package/dist/index.d.ts +155 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +29 -0
- package/dist/index.mjs.map +1 -0
- package/dist/local-api-handler-pages.d.mts +29 -0
- package/dist/local-api-handler-pages.d.ts +29 -0
- package/dist/local-api-handler-pages.js +2 -0
- package/dist/local-api-handler-pages.js.map +1 -0
- package/dist/local-api-handler-pages.mjs +2 -0
- package/dist/local-api-handler-pages.mjs.map +1 -0
- package/dist/local-api-handler.d.mts +12 -0
- package/dist/local-api-handler.d.ts +12 -0
- package/dist/local-api-handler.js +2 -0
- package/dist/local-api-handler.js.map +1 -0
- package/dist/local-api-handler.mjs +2 -0
- package/dist/local-api-handler.mjs.map +1 -0
- package/dist/local-viewer.d.mts +1 -0
- package/dist/local-viewer.d.ts +1 -0
- package/dist/local-viewer.js +96 -0
- package/dist/local-viewer.js.map +1 -0
- package/dist/local-viewer.mjs +96 -0
- package/dist/local-viewer.mjs.map +1 -0
- package/dist/types-CjgYXVc_.d.mts +164 -0
- package/dist/types-CjgYXVc_.d.ts +164 -0
- package/package.json +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/breadcrumbs.ts","../src/sanitizer.ts","../src/fingerprint.ts","../src/rate-limiter.ts","../src/env-detector.ts","../src/prompt-builder.ts","../src/transport.ts","../src/client.ts"],"names":["createBreadcrumbStore","capacity","buffer","head","size","crumb","entry","isoTimestamp","result","start","idx","n","count","i","DEFAULT_SENSITIVE_KEYS","SENSITIVE_HEADERS","REDACTED","MAX_STRING_LENGTH","buildKeyPattern","additionalKeys","escaped","k","sanitize","obj","pattern","seen","walk","value","key","item","generateFingerprint","error","normalisedMessage","normaliseMessage","frames","extractTopFrames","input","djb2","msg","stack","lines","line","trimmed","v8Match","fn","file","normalisePath","smMatch","p","str","hash","createRateLimiter","globalMax","perFingerprintMax","buckets","globalTimestamps","prune","timestamps","now","cutoff","fingerprint","fpTimestamps","ts","cached","detectEnvironment","info","isBrowser","detectNodeOS","ua","browserInfo","parseBrowserUA","parseOS","detectDeviceType","detectFramework","platform","patterns","name","regex","match","width","buildFixPrompt","event","sections","location","extractLocation","l","formatOperation","formatRequest","formatBreadcrumbs","formatEnvironment","v8","sm","op","req","crumbs","recent","time","formatTime","iso","d","h","m","s","env","entries","label","createTransport","config","createConsoleTransport","createRemoteTransport","createLocalTransport","_config","title","createLocalFileTransport","createLocalClientTransport","fsPromises","pathModule","baseDir","initialised","init","fs","path","ensureGitignore","gitignorePath","content","fp","eventDir","eventFile","eventPath","tmpEventPath","safeStringify","latestPath","tmpLatestPath","promptFile","promptPath","tmpPromptPath","updateIssuesIndex","indexPath","issues","raw","existing","userId","tmpIndexPath","queue","consoleFallback","postEvents","events","res","ok","batch","endpoint","projectKey","maxRetries","batchSize","flushIntervalMs","flushTimer","stopped","backoffDelays","sendBatch","attempt","retryAfter","sleep","startFlushing","registerBeacon","payload","ms","resolve","SDK_NAME","SDK_VERSION","_client","initUncaught","UncaughtClient","getClient","generateUUID","context","errorInfo","normaliseError","environment","eventId","err","message","level","user","args"],"mappings":"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","file":"index.js","sourcesContent":["// ---------------------------------------------------------------------------\n// @uncaughtdev/core — breadcrumb ring-buffer store\n// ---------------------------------------------------------------------------\n\nimport type { Breadcrumb, BreadcrumbStore } from './types';\nimport { isoTimestamp } from './utils';\n\n/**\n * Create a fixed-capacity ring-buffer store for breadcrumbs.\n *\n * - O(1) `add`\n * - Oldest entries are silently overwritten when capacity is reached.\n * - Returned arrays are always copies — callers cannot mutate internal state.\n *\n * @param capacity Maximum breadcrumbs retained. Defaults to 20.\n */\nexport function createBreadcrumbStore(capacity: number = 20): BreadcrumbStore {\n const buffer: Array<Breadcrumb | undefined> = new Array(capacity);\n let head = 0; // next write index\n let size = 0; // current number of entries\n\n const store: BreadcrumbStore = {\n add(crumb: Omit<Breadcrumb, 'timestamp'>): void {\n const entry: Breadcrumb = {\n ...crumb,\n timestamp: isoTimestamp(),\n };\n\n buffer[head] = entry;\n head = (head + 1) % capacity;\n\n if (size < capacity) {\n size++;\n }\n },\n\n getAll(): Breadcrumb[] {\n if (size === 0) return [];\n\n const result: Breadcrumb[] = [];\n\n // The oldest entry sits at `(head - size + capacity) % capacity`\n const start = (head - size + capacity) % capacity;\n\n for (let i = 0; i < size; i++) {\n const idx = (start + i) % capacity;\n const entry = buffer[idx];\n if (entry) {\n // Return a shallow copy so callers cannot mutate internal data.\n result.push({ ...entry });\n }\n }\n\n return result;\n },\n\n getLast(n: number): Breadcrumb[] {\n if (n <= 0 || size === 0) return [];\n\n const count = Math.min(n, size);\n const result: Breadcrumb[] = [];\n\n // Walk backwards from the most recent entry.\n for (let i = 0; i < count; i++) {\n const idx = (head - 1 - i + capacity) % capacity;\n const entry = buffer[idx];\n if (entry) {\n result.unshift({ ...entry });\n }\n }\n\n return result;\n },\n\n clear(): void {\n buffer.fill(undefined);\n head = 0;\n size = 0;\n },\n };\n\n return store;\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — PII / secret sanitizer\n// ---------------------------------------------------------------------------\n\n/** Default key patterns that are always redacted. */\nconst DEFAULT_SENSITIVE_KEYS: string[] = [\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'authorization',\n 'credit_card',\n 'creditcard',\n 'card_number',\n 'cvv',\n 'ssn',\n 'social_security',\n 'private_key',\n 'access_token',\n 'refresh_token',\n 'session_id',\n 'cookie',\n];\n\n/** Headers that are always stripped regardless of key matching. */\nconst SENSITIVE_HEADERS = new Set(['authorization', 'cookie', 'set-cookie']);\n\nconst REDACTED = '[REDACTED]';\nconst MAX_STRING_LENGTH = 2048;\n\n/**\n * Build a single RegExp that matches any of the sensitive key patterns\n * (case-insensitive).\n */\nfunction buildKeyPattern(additionalKeys: string[] = []): RegExp {\n const all = [...DEFAULT_SENSITIVE_KEYS, ...additionalKeys];\n // Escape special regex characters in user-supplied keys\n const escaped = all.map((k) => k.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n return new RegExp(escaped.join('|'), 'i');\n}\n\n/**\n * Deep-clone and sanitise `obj`, redacting values whose keys match\n * sensitive patterns.\n *\n * - Handles circular references (returns `\"[Circular]\"`).\n * - Truncates strings longer than 2 048 characters.\n * - Never mutates the original object.\n *\n * @param obj - The value to sanitise.\n * @param additionalKeys - Extra key patterns to redact on top of the defaults.\n */\nexport function sanitize<T>(obj: T, additionalKeys?: string[]): T {\n const pattern = buildKeyPattern(additionalKeys);\n const seen = new WeakSet();\n\n function walk(value: unknown, key?: string): unknown {\n // Redact if the current key is sensitive\n if (key && pattern.test(key)) {\n return REDACTED;\n }\n\n // Primitives\n if (value === null || value === undefined) return value;\n\n if (typeof value === 'string') {\n return value.length > MAX_STRING_LENGTH\n ? value.slice(0, MAX_STRING_LENGTH) + '...[truncated]'\n : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (typeof value === 'function' || typeof value === 'symbol') {\n return undefined;\n }\n\n // Dates — return ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // Arrays\n if (Array.isArray(value)) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const result = value.map((item) => walk(item));\n seen.delete(value);\n return result;\n }\n\n // Plain objects\n if (typeof value === 'object') {\n if (seen.has(value as object)) return '[Circular]';\n seen.add(value as object);\n\n const result: Record<string, unknown> = {};\n\n for (const k of Object.keys(value as Record<string, unknown>)) {\n // Always strip sensitive headers\n if (SENSITIVE_HEADERS.has(k.toLowerCase())) {\n result[k] = REDACTED;\n continue;\n }\n\n result[k] = walk((value as Record<string, unknown>)[k], k);\n }\n\n seen.delete(value as object);\n return result;\n }\n\n return value;\n }\n\n return walk(obj) as T;\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — error fingerprinting\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a stable fingerprint for an error so that duplicate occurrences\n * of the same bug are grouped together.\n *\n * The fingerprint is an 8-character hex string derived from:\n * 1. The normalised error message (volatile parts stripped).\n * 2. The top 3 stack frames (file + function name, no line/col numbers).\n *\n * @param error - An object with at least `message` and optionally `stack` and `type`.\n */\nexport function generateFingerprint(error: {\n message?: string;\n type?: string;\n stack?: string;\n}): string {\n const normalisedMessage = normaliseMessage(error.message ?? '');\n const frames = extractTopFrames(error.stack ?? '', 3);\n const input = [error.type ?? 'Error', normalisedMessage, ...frames].join(\n '\\n'\n );\n return djb2(input);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Strip volatile substrings from an error message so that trivially-different\n * occurrences of the same bug hash identically.\n */\nfunction normaliseMessage(msg: string): string {\n return (\n msg\n // UUIDs (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)\n .replace(\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,\n '<UUID>'\n )\n // Hex strings (8+ hex chars in a row)\n .replace(/\\b[0-9a-f]{8,}\\b/gi, '<HEX>')\n // Numbers longer than 3 digits\n .replace(/\\b\\d{4,}\\b/g, '<NUM>')\n // ISO timestamps\n .replace(\n /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[.\\d]*Z?/g,\n '<TIMESTAMP>'\n )\n // Hashed file paths — replace the hash portion (e.g. chunk-abc123.js → chunk-<HASH>.js)\n .replace(\n /([/\\\\])[a-zA-Z0-9_-]+[-.]([a-f0-9]{6,})\\.(js|ts|mjs|cjs|jsx|tsx)/g,\n '$1<FILE>.$3'\n )\n .trim()\n );\n}\n\n/**\n * Extract the top N stack frames as normalised \"file:function\" strings.\n * Line and column numbers are intentionally omitted so that minor code\n * changes do not alter the fingerprint.\n */\nfunction extractTopFrames(stack: string, count: number): string[] {\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: string[] = [];\n\n for (const line of lines) {\n if (frames.length >= count) break;\n\n const trimmed = line.trim();\n\n // V8 format: \" at FunctionName (file:line:col)\"\n // or \" at file:line:col\"\n const v8Match = trimmed.match(\n /at\\s+(?:(.+?)\\s+\\()?(?:(.+?):\\d+:\\d+)\\)?/\n );\n if (v8Match) {\n const fn = v8Match[1] || '<anonymous>';\n const file = normalisePath(v8Match[2] || '<unknown>');\n frames.push(`${file}:${fn}`);\n continue;\n }\n\n // SpiderMonkey / JavaScriptCore: \"functionName@file:line:col\"\n const smMatch = trimmed.match(/^(.+?)@(.+?):\\d+:\\d+/);\n if (smMatch) {\n const fn = smMatch[1] || '<anonymous>';\n const file = normalisePath(smMatch[2] || '<unknown>');\n frames.push(`${file}:${fn}`);\n continue;\n }\n }\n\n return frames;\n}\n\n/**\n * Normalise a file path by stripping query strings / hashes and collapsing\n * absolute filesystem prefixes.\n */\nfunction normalisePath(p: string): string {\n return p\n .replace(/[?#].*$/, '') // strip query / hash\n .replace(/^.*\\/node_modules\\//, 'node_modules/') // collapse deep paths\n .replace(/^(https?:\\/\\/[^/]+)/, '') // strip origin in URLs\n .replace(/^.*[/\\\\]/, ''); // keep only filename\n}\n\n/**\n * DJB2 hash → 8-character lowercase hex string.\n */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n // hash * 33 + char\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n // Convert to unsigned 32-bit then to 8-char hex\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — sliding-window rate limiter\n// ---------------------------------------------------------------------------\n\n/** Window duration in milliseconds (60 seconds). */\nconst WINDOW_MS = 60_000;\n\nexport interface RateLimiter {\n /**\n * Returns `true` if the event identified by `fingerprint` is allowed\n * through, `false` if it should be dropped.\n */\n shouldAllow(fingerprint: string): boolean;\n}\n\n/**\n * Create a rate limiter that enforces:\n * - A global maximum of `globalMax` events per 60-second window.\n * - A per-fingerprint maximum of `perFingerprintMax` events per 60-second window.\n *\n * Stale timestamps are lazily cleaned on every call to `shouldAllow`.\n *\n * @param globalMax Max events across all fingerprints. Defaults to 30.\n * @param perFingerprintMax Max events for a single fingerprint. Defaults to 5.\n */\nexport function createRateLimiter(\n globalMax: number = 30,\n perFingerprintMax: number = 5\n): RateLimiter {\n /** Per-fingerprint timestamp arrays. */\n const buckets = new Map<string, number[]>();\n /** Global timestamp array. */\n let globalTimestamps: number[] = [];\n\n /**\n * Remove timestamps older than the sliding window from an array (in-place)\n * and return the pruned array.\n */\n function prune(timestamps: number[], now: number): number[] {\n const cutoff = now - WINDOW_MS;\n // Find the first index that is within the window\n let start = 0;\n while (start < timestamps.length && timestamps[start] <= cutoff) {\n start++;\n }\n if (start > 0) {\n timestamps.splice(0, start);\n }\n return timestamps;\n }\n\n return {\n shouldAllow(fingerprint: string): boolean {\n const now = Date.now();\n\n // --- Global limit ---\n globalTimestamps = prune(globalTimestamps, now);\n if (globalTimestamps.length >= globalMax) {\n return false;\n }\n\n // --- Per-fingerprint limit ---\n let fpTimestamps = buckets.get(fingerprint);\n if (!fpTimestamps) {\n fpTimestamps = [];\n buckets.set(fingerprint, fpTimestamps);\n }\n prune(fpTimestamps, now);\n\n if (fpTimestamps.length >= perFingerprintMax) {\n return false;\n }\n\n // Record this event\n globalTimestamps.push(now);\n fpTimestamps.push(now);\n\n // Periodic cleanup: remove empty buckets to prevent unbounded memory growth\n if (buckets.size > 1000) {\n for (const [key, ts] of buckets) {\n if (ts.length === 0) {\n buckets.delete(key);\n }\n }\n }\n\n return true;\n },\n };\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — runtime / platform environment detector\n// ---------------------------------------------------------------------------\n\nimport type { EnvironmentInfo } from './types';\n\n/** Cached result so detection only runs once per process / page-load. */\nlet cached: EnvironmentInfo | undefined;\n\n/**\n * Detect the current runtime environment.\n *\n * - SSR-safe: every global access is guarded.\n * - Result is cached after the first invocation.\n */\nexport function detectEnvironment(): EnvironmentInfo {\n if (cached) return cached;\n\n const info: EnvironmentInfo = {};\n\n try {\n const isBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n const isNode =\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null;\n\n // ----- Runtime ---------------------------------------------------------\n if (isNode) {\n info.runtime = 'node';\n info.runtimeVersion = process.versions.node;\n info.platform = process.platform;\n info.os = detectNodeOS();\n } else if (isBrowser) {\n info.runtime = 'browser';\n info.platform = 'web';\n\n const ua = navigator?.userAgent ?? '';\n const browserInfo = parseBrowserUA(ua);\n info.browser = browserInfo.name;\n info.browserVersion = browserInfo.version;\n info.os = parseOS(ua);\n info.deviceType = detectDeviceType();\n info.url = location?.href;\n info.locale = navigator?.language;\n info.timezone = Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone;\n }\n\n // ----- Framework detection (works in both Node & browser) ---------------\n detectFramework(info);\n } catch {\n // Silent — environment detection must never throw.\n }\n\n cached = info;\n return info;\n}\n\n/**\n * Reset the cached environment (useful for testing).\n */\nexport function resetEnvironmentCache(): void {\n cached = undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction detectNodeOS(): string | undefined {\n try {\n const platform = process.platform;\n const map: Record<string, string> = {\n darwin: 'macOS',\n win32: 'Windows',\n linux: 'Linux',\n freebsd: 'FreeBSD',\n sunos: 'SunOS',\n };\n return map[platform] ?? platform;\n } catch {\n return undefined;\n }\n}\n\ninterface BrowserInfo {\n name?: string;\n version?: string;\n}\n\nfunction parseBrowserUA(ua: string): BrowserInfo {\n // Order matters — check more specific browsers first.\n const patterns: Array<{ name: string; regex: RegExp }> = [\n { name: 'Edge', regex: /Edg(?:e|A|iOS)?\\/(\\d+[\\d.]*)/ },\n { name: 'Opera', regex: /(?:OPR|Opera)\\/(\\d+[\\d.]*)/ },\n { name: 'Samsung Internet', regex: /SamsungBrowser\\/(\\d+[\\d.]*)/ },\n { name: 'UC Browser', regex: /UCBrowser\\/(\\d+[\\d.]*)/ },\n { name: 'Firefox', regex: /Firefox\\/(\\d+[\\d.]*)/ },\n { name: 'Chrome', regex: /Chrome\\/(\\d+[\\d.]*)/ },\n { name: 'Safari', regex: /Version\\/(\\d+[\\d.]*).*Safari/ },\n ];\n\n for (const { name, regex } of patterns) {\n const match = ua.match(regex);\n if (match) {\n return { name, version: match[1] };\n }\n }\n\n return {};\n}\n\nfunction parseOS(ua: string): string | undefined {\n if (/Windows/i.test(ua)) return 'Windows';\n if (/Mac OS X|macOS/i.test(ua)) return 'macOS';\n if (/Android/i.test(ua)) return 'Android';\n if (/iPhone|iPad|iPod/i.test(ua)) return 'iOS';\n if (/Linux/i.test(ua)) return 'Linux';\n if (/CrOS/i.test(ua)) return 'ChromeOS';\n return undefined;\n}\n\nfunction detectDeviceType(): string | undefined {\n try {\n if (typeof window === 'undefined') return undefined;\n\n const width = window.screen?.width ?? window.innerWidth;\n\n if (width <= 480) return 'mobile';\n if (width <= 1024) return 'tablet';\n return 'desktop';\n } catch {\n return undefined;\n }\n}\n\nfunction detectFramework(info: EnvironmentInfo): void {\n try {\n // ----- Browser-side markers -------------------------------------------\n if (typeof window !== 'undefined') {\n // Next.js injects __NEXT_DATA__\n if ((window as any).__NEXT_DATA__) {\n info.framework = 'next';\n info.frameworkVersion =\n (window as any).__NEXT_DATA__?.buildId ?? undefined;\n }\n // Remix injects __remixContext\n else if ((window as any).__remixContext) {\n info.framework = 'remix';\n }\n // Nuxt injects __NUXT__\n else if ((window as any).__NUXT__) {\n info.framework = 'nuxt';\n }\n }\n\n // ----- Node-side markers -----------------------------------------------\n if (\n typeof process !== 'undefined' &&\n process.env != null\n ) {\n // Framework env vars set during SSR / server build\n if (!info.framework) {\n if (process.env.__NEXT_PRIVATE_ORIGIN !== undefined || process.env.NEXT_RUNTIME) {\n info.framework = 'next';\n } else if (process.env.REMIX_DEV_ORIGIN !== undefined) {\n info.framework = 'remix';\n }\n }\n\n // Hosting platform markers\n if (process.env.VERCEL) {\n info.platform = info.platform ?? 'vercel';\n } else if (process.env.RAILWAY_PROJECT_ID) {\n info.platform = info.platform ?? 'railway';\n } else if (process.env.FLY_APP_NAME) {\n info.platform = info.platform ?? 'fly';\n } else if (process.env.AWS_LAMBDA_FUNCTION_NAME) {\n info.platform = info.platform ?? 'aws-lambda';\n } else if (process.env.GOOGLE_CLOUD_PROJECT) {\n info.platform = info.platform ?? 'gcp';\n }\n }\n\n // ----- Vite (import.meta.env) ------------------------------------------\n try {\n if (typeof (import.meta as any)?.env?.VITE_USER_NODE_ENV !== 'undefined') {\n if (!info.framework) {\n info.framework = 'vite';\n }\n }\n } catch {\n // import.meta may not exist in CJS contexts\n }\n } catch {\n // Silent — never throw during detection.\n }\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — fix-prompt builder\n// ---------------------------------------------------------------------------\n\nimport type { UncaughtEvent, Breadcrumb, EnvironmentInfo, OperationInfo, RequestInfo } from './types';\n\n/**\n * Build a structured Markdown prompt that can be pasted into an AI assistant\n * to diagnose and fix the production error described by `event`.\n *\n * Empty sections are omitted to keep the prompt concise.\n */\nexport function buildFixPrompt(event: Partial<UncaughtEvent>): string {\n const sections: string[] = [];\n\n // ----- Intro -------------------------------------------------------------\n sections.push(\n 'I have a production bug in my application that I need help diagnosing and fixing.\\n'\n );\n\n // ----- Error -------------------------------------------------------------\n if (event.error) {\n const location = extractLocation(event.error.stack);\n const lines: string[] = ['## Error', ''];\n lines.push(`- **Type:** ${event.error.type || 'Error'}`);\n lines.push(`- **Message:** ${event.error.message || '(no message)'}`);\n if (location) {\n lines.push(`- **Location:** ${location}`);\n }\n sections.push(lines.join('\\n'));\n }\n\n // ----- Stack Trace -------------------------------------------------------\n if (event.error?.stack) {\n const frames = event.error.stack\n .split('\\n')\n .slice(0, 15)\n .map((l) => l.trimEnd())\n .join('\\n');\n sections.push(`## Stack Trace\\n\\n\\`\\`\\`\\n${frames}\\n\\`\\`\\``);\n }\n\n // ----- Failed Operation --------------------------------------------------\n if (event.operation) {\n sections.push(formatOperation(event.operation));\n }\n\n // ----- HTTP Request Context ----------------------------------------------\n if (event.request) {\n sections.push(formatRequest(event.request));\n }\n\n // ----- User Session (last 5 breadcrumbs) ---------------------------------\n if (event.breadcrumbs && event.breadcrumbs.length > 0) {\n sections.push(formatBreadcrumbs(event.breadcrumbs));\n }\n\n // ----- Environment -------------------------------------------------------\n if (event.environment) {\n sections.push(formatEnvironment(event.environment));\n }\n\n // ----- React Component Stack ---------------------------------------------\n if (event.error?.componentStack) {\n sections.push(\n `## React Component Stack\\n\\n\\`\\`\\`\\n${event.error.componentStack.trim()}\\n\\`\\`\\``\n );\n }\n\n // ----- What I need -------------------------------------------------------\n sections.push(\n [\n '## What I need',\n '',\n '1. **Root cause analysis** — explain why this error is occurring.',\n '2. **A fix** — provide the corrected code with an explanation of the changes.',\n '3. **Prevention** — suggest any guards or tests to prevent this from happening again.',\n ].join('\\n')\n );\n\n return sections.join('\\n\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the top-most location (file:line:col) from a stack trace string.\n */\nfunction extractLocation(stack?: string): string | undefined {\n if (!stack) return undefined;\n\n for (const line of stack.split('\\n')) {\n const trimmed = line.trim();\n\n // V8: \" at fn (file:line:col)\"\n const v8 = trimmed.match(/at\\s+(?:.+?\\s+\\()?(.+?:\\d+:\\d+)\\)?/);\n if (v8) return v8[1];\n\n // SpiderMonkey / JSC: \"fn@file:line:col\"\n const sm = trimmed.match(/@(.+?:\\d+:\\d+)/);\n if (sm) return sm[1];\n }\n\n return undefined;\n}\n\nfunction formatOperation(op: OperationInfo): string {\n const lines: string[] = ['## Failed Operation', ''];\n lines.push(`- **Provider:** ${op.provider}`);\n lines.push(`- **Type:** ${op.type}`);\n lines.push(`- **Method:** ${op.method}`);\n if (op.params) {\n lines.push(`- **Params:**`);\n lines.push('```json');\n lines.push(JSON.stringify(op.params, null, 2));\n lines.push('```');\n }\n if (op.errorCode) {\n lines.push(`- **Error Code:** ${op.errorCode}`);\n }\n if (op.errorDetails) {\n lines.push(`- **Error Details:** ${op.errorDetails}`);\n }\n return lines.join('\\n');\n}\n\nfunction formatRequest(req: RequestInfo): string {\n const lines: string[] = ['## HTTP Request Context', ''];\n if (req.method) lines.push(`- **Method:** ${req.method}`);\n if (req.url) lines.push(`- **URL:** ${req.url}`);\n if (req.body) {\n lines.push(`- **Body:**`);\n lines.push('```json');\n lines.push(\n typeof req.body === 'string'\n ? req.body\n : JSON.stringify(req.body, null, 2)\n );\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\nfunction formatBreadcrumbs(crumbs: Breadcrumb[]): string {\n // Take the last 5 breadcrumbs\n const recent = crumbs.slice(-5);\n const lines: string[] = ['## User Session', ''];\n\n for (const crumb of recent) {\n const time = formatTime(crumb.timestamp);\n lines.push(`- \\`${time}\\` **[${crumb.type}]** ${crumb.message}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Extract HH:MM:SS from an ISO timestamp.\n */\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n } catch {\n return iso;\n }\n}\n\nfunction formatEnvironment(env: EnvironmentInfo): string {\n const lines: string[] = ['## Environment', ''];\n const entries: Array<[string, string | undefined]> = [\n ['Framework', env.framework],\n ['Framework Version', env.frameworkVersion],\n ['Runtime', env.runtime],\n ['Runtime Version', env.runtimeVersion],\n ['Platform', env.platform],\n ['Browser', env.browser ? `${env.browser} ${env.browserVersion ?? ''}`.trim() : undefined],\n ['OS', env.os],\n ['Device', env.deviceType],\n ['Locale', env.locale],\n ['Timezone', env.timezone],\n ['URL', env.url],\n ];\n\n for (const [label, value] of entries) {\n if (value) {\n lines.push(`- **${label}:** ${value}`);\n }\n }\n\n return lines.join('\\n');\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — transport layer (console / local-file / remote)\n// ---------------------------------------------------------------------------\n\nimport type {\n Transport,\n UncaughtConfig,\n UncaughtEvent,\n IssueEntry,\n} from './types';\nimport { safeStringify } from './utils';\n\n// ===================================================================\n// Factory\n// ===================================================================\n\n/**\n * Create the appropriate transport strategy based on config.\n */\nexport function createTransport(config: UncaughtConfig): Transport {\n const mode = config.transport ?? 'local';\n\n switch (mode) {\n case 'console':\n return createConsoleTransport(config);\n case 'remote':\n return createRemoteTransport(config);\n case 'local':\n default:\n return createLocalTransport(config);\n }\n}\n\n// ===================================================================\n// Console Transport\n// ===================================================================\n\nfunction createConsoleTransport(_config: UncaughtConfig): Transport {\n return {\n send(event: UncaughtEvent): void {\n try {\n const title = `[uncaught] ${event.error.type}: ${event.error.message}`;\n\n if (typeof console.group === 'function') {\n console.group(title);\n } else {\n console.log(`--- ${title} ---`);\n }\n\n console.error('Error:', event.error.message);\n if (event.error.stack) {\n console.log('Stack:', event.error.stack);\n }\n console.log('Event ID:', event.eventId);\n console.log('Fingerprint:', event.fingerprint);\n console.log('Breadcrumbs:', event.breadcrumbs);\n\n if (event.fixPrompt) {\n console.log('Fix Prompt:\\n', event.fixPrompt);\n }\n\n if (typeof console.groupEnd === 'function') {\n console.groupEnd();\n }\n } catch {\n // Never throw from transport.\n }\n },\n\n async flush(): Promise<void> {\n // Nothing to flush for console transport.\n },\n };\n}\n\n// ===================================================================\n// Local File Transport\n// ===================================================================\n\n/**\n * The local transport behaves differently depending on whether `fs` is\n * available (server / Node.js) or not (browser).\n *\n * **Server:** writes events directly to the `.uncaught/` directory.\n * **Browser:** POSTs to `/api/uncaught/local` and falls back to console.\n */\nfunction createLocalTransport(config: UncaughtConfig): Transport {\n // Detect server vs browser at transport creation time.\n const isServer = typeof process !== 'undefined' && process.versions?.node != null;\n\n if (isServer) {\n return createLocalFileTransport(config);\n }\n\n return createLocalClientTransport(config);\n}\n\n// ---------------------------------------------------------------------------\n// Local File Transport (Server / Node.js)\n// ---------------------------------------------------------------------------\n\ninterface FsModule {\n mkdir: (path: string, options: { recursive: boolean }) => Promise<void>;\n writeFile: (path: string, data: string, encoding: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n rename: (from: string, to: string) => Promise<void>;\n access: (path: string) => Promise<void>;\n appendFile: (path: string, data: string) => Promise<void>;\n}\n\ninterface PathModule {\n join: (...parts: string[]) => string;\n resolve: (...parts: string[]) => string;\n}\n\nfunction createLocalFileTransport(config: UncaughtConfig): Transport {\n let fsPromises: FsModule | undefined;\n let pathModule: PathModule | undefined;\n let baseDir: string = '';\n let initialised = false;\n\n async function init(): Promise<void> {\n if (initialised) return;\n\n // Dynamic imports so this module can still be loaded in browsers without\n // causing a hard crash at parse time.\n const fs = await import('fs/promises');\n const path = await import('path');\n fsPromises = fs as unknown as FsModule;\n pathModule = path as unknown as PathModule;\n\n baseDir = config.localOutputDir ?? pathModule.resolve(process.cwd(), '.uncaught');\n\n // Ensure directory structure\n await fsPromises.mkdir(pathModule.join(baseDir, 'events'), { recursive: true });\n await fsPromises.mkdir(pathModule.join(baseDir, 'fix-prompts'), { recursive: true });\n\n // Auto-add .uncaught/ to .gitignore\n await ensureGitignore(fsPromises, pathModule);\n\n initialised = true;\n }\n\n async function ensureGitignore(fs: FsModule, path: PathModule): Promise<void> {\n try {\n const gitignorePath = path.resolve(process.cwd(), '.gitignore');\n let content = '';\n try {\n content = await fs.readFile(gitignorePath, 'utf-8');\n } catch {\n // File doesn't exist yet — that's fine.\n }\n\n if (!content.includes('.uncaught')) {\n const line = '\\n# Uncaught local error store\\n.uncaught/\\n';\n await fs.appendFile(gitignorePath, line);\n }\n } catch {\n // Non-critical — swallow.\n }\n }\n\n return {\n async send(event: UncaughtEvent): Promise<void> {\n try {\n await init();\n if (!fsPromises || !pathModule) return;\n\n const fp = event.fingerprint;\n const eventDir = pathModule.join(baseDir, 'events', fp);\n await fsPromises.mkdir(eventDir, { recursive: true });\n\n // --- Write timestamped event file (atomic: .tmp → rename) ----------\n const ts = event.timestamp.replace(/[:.]/g, '-');\n const eventFile = `event-${ts}.json`;\n const eventPath = pathModule.join(eventDir, eventFile);\n const tmpEventPath = eventPath + '.tmp';\n await fsPromises.writeFile(tmpEventPath, safeStringify(event), 'utf-8');\n await fsPromises.rename(tmpEventPath, eventPath);\n\n // --- Write / overwrite latest.json ---------------------------------\n const latestPath = pathModule.join(eventDir, 'latest.json');\n const tmpLatestPath = latestPath + '.tmp';\n await fsPromises.writeFile(tmpLatestPath, safeStringify(event), 'utf-8');\n await fsPromises.rename(tmpLatestPath, latestPath);\n\n // --- Write fix-prompt Markdown file --------------------------------\n const promptFile = `${fp}.md`;\n const promptPath = pathModule.join(baseDir, 'fix-prompts', promptFile);\n const tmpPromptPath = promptPath + '.tmp';\n await fsPromises.writeFile(tmpPromptPath, event.fixPrompt, 'utf-8');\n await fsPromises.rename(tmpPromptPath, promptPath);\n\n // --- Update issues.json index -------------------------------------\n await updateIssuesIndex(\n fsPromises,\n pathModule,\n baseDir,\n event,\n eventFile,\n promptFile\n );\n } catch {\n // Never crash the host app.\n }\n },\n\n async flush(): Promise<void> {\n // Local file transport writes synchronously per-event; nothing to flush.\n },\n };\n}\n\n/**\n * Read, update, and atomically write the `issues.json` index.\n */\nasync function updateIssuesIndex(\n fs: FsModule,\n path: PathModule,\n baseDir: string,\n event: UncaughtEvent,\n eventFile: string,\n promptFile: string\n): Promise<void> {\n const indexPath = path.join(baseDir, 'issues.json');\n\n let issues: IssueEntry[] = [];\n try {\n const raw = await fs.readFile(indexPath, 'utf-8');\n issues = JSON.parse(raw) as IssueEntry[];\n } catch {\n // File doesn't exist or is malformed — start fresh.\n }\n\n const existing = issues.find((i) => i.fingerprint === event.fingerprint);\n const userId = event.user?.id ?? event.user?.email ?? 'anonymous';\n\n if (existing) {\n existing.count += 1;\n existing.lastSeen = event.timestamp;\n existing.latestEventFile = eventFile;\n existing.fixPromptFile = promptFile;\n if (!existing.affectedUsers.includes(userId)) {\n existing.affectedUsers.push(userId);\n }\n // Re-open if previously resolved\n if (existing.status === 'resolved') {\n existing.status = 'open';\n }\n } else {\n issues.push({\n fingerprint: event.fingerprint,\n title: event.error.message,\n errorType: event.error.type,\n count: 1,\n affectedUsers: [userId],\n firstSeen: event.timestamp,\n lastSeen: event.timestamp,\n status: 'open',\n fixPromptFile: promptFile,\n latestEventFile: eventFile,\n });\n }\n\n const tmpIndexPath = indexPath + '.tmp';\n await fs.writeFile(tmpIndexPath, JSON.stringify(issues, null, 2), 'utf-8');\n await fs.rename(tmpIndexPath, indexPath);\n}\n\n// ---------------------------------------------------------------------------\n// Local Client Transport (Browser → POST /api/uncaught/local)\n// ---------------------------------------------------------------------------\n\nfunction createLocalClientTransport(_config: UncaughtConfig): Transport {\n const queue: UncaughtEvent[] = [];\n const consoleFallback = createConsoleTransport(_config);\n\n async function postEvents(events: UncaughtEvent[]): Promise<boolean> {\n try {\n const res = await fetch('/api/uncaught/local', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: safeStringify({ events }),\n });\n\n return res.ok || res.status === 202;\n } catch {\n return false;\n }\n }\n\n return {\n send(event: UncaughtEvent): void {\n queue.push(event);\n\n // Attempt to send immediately\n postEvents([event]).then((ok) => {\n if (!ok) {\n // Fallback to console\n consoleFallback.send(event);\n }\n }).catch(() => {\n consoleFallback.send(event);\n });\n },\n\n async flush(): Promise<void> {\n if (queue.length === 0) return;\n\n const batch = queue.splice(0, queue.length);\n const ok = await postEvents(batch);\n if (!ok) {\n // Fallback: log remaining to console\n for (const event of batch) {\n consoleFallback.send(event);\n }\n }\n },\n };\n}\n\n// ===================================================================\n// Remote Transport\n// ===================================================================\n\nfunction createRemoteTransport(config: UncaughtConfig): Transport {\n const endpoint = config.endpoint ?? '';\n const projectKey = config.projectKey ?? '';\n const maxRetries = 3;\n const batchSize = 10;\n const flushIntervalMs = 5_000;\n\n const queue: UncaughtEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n let stopped = false;\n\n // Backoff delays in ms for retries (1s, 2s, 4s)\n const backoffDelays = [1000, 2000, 4000];\n\n async function sendBatch(events: UncaughtEvent[]): Promise<void> {\n if (events.length === 0 || stopped) return;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(projectKey ? { 'X-Project-Key': projectKey } : {}),\n },\n body: safeStringify({ events }),\n });\n\n if (res.ok || res.status === 202) {\n return; // Success\n }\n\n if (res.status === 401) {\n // Unauthorized — stop sending entirely.\n stopped = true;\n if (flushTimer) clearInterval(flushTimer);\n return;\n }\n\n if (res.status === 429) {\n // Rate limited — use longer backoff\n const retryAfter = parseInt(\n res.headers?.get?.('Retry-After') ?? '10',\n 10\n );\n await sleep(retryAfter * 1000);\n continue;\n }\n\n // Other server errors — retry with backoff\n if (attempt < maxRetries) {\n await sleep(backoffDelays[attempt] ?? 4000);\n }\n } catch {\n // Network error — retry\n if (attempt < maxRetries) {\n await sleep(backoffDelays[attempt] ?? 4000);\n }\n }\n }\n // All retries exhausted — events are dropped silently.\n }\n\n function startFlushing(): void {\n if (flushTimer) return;\n flushTimer = setInterval(() => {\n if (queue.length > 0) {\n const batch = queue.splice(0, batchSize);\n sendBatch(batch).catch(() => {\n // Swallow — never crash.\n });\n }\n }, flushIntervalMs);\n\n // Ensure the timer does not prevent Node.js from exiting.\n if (typeof flushTimer === 'object' && 'unref' in flushTimer) {\n (flushTimer as { unref: () => void }).unref();\n }\n }\n\n // Register sendBeacon on page unload (browser only)\n function registerBeacon(): void {\n try {\n if (\n typeof window !== 'undefined' &&\n typeof navigator?.sendBeacon === 'function'\n ) {\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden' && queue.length > 0) {\n const payload = safeStringify({ events: queue.splice(0, queue.length) });\n navigator.sendBeacon(endpoint, payload);\n }\n });\n\n window.addEventListener('pagehide', () => {\n if (queue.length > 0) {\n const payload = safeStringify({ events: queue.splice(0, queue.length) });\n navigator.sendBeacon(endpoint, payload);\n }\n });\n }\n } catch {\n // Not in a browser — that's fine.\n }\n }\n\n startFlushing();\n registerBeacon();\n\n return {\n send(event: UncaughtEvent): void {\n if (stopped) return;\n\n queue.push(event);\n\n // Flush immediately if batch size reached\n if (queue.length >= batchSize) {\n const batch = queue.splice(0, batchSize);\n sendBatch(batch).catch(() => {\n // Swallow.\n });\n }\n },\n\n async flush(): Promise<void> {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = undefined;\n }\n\n while (queue.length > 0) {\n const batch = queue.splice(0, batchSize);\n await sendBatch(batch);\n }\n },\n };\n}\n\n// ===================================================================\n// Helpers\n// ===================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — UncaughtClient (SDK entry-point)\n// ---------------------------------------------------------------------------\n\nimport type {\n UncaughtConfig,\n UncaughtEvent,\n Breadcrumb,\n BreadcrumbStore,\n Transport,\n SeverityLevel,\n UserInfo,\n RequestInfo,\n OperationInfo,\n} from './types';\n\nimport { generateUUID, isoTimestamp } from './utils';\nimport { createBreadcrumbStore } from './breadcrumbs';\nimport { sanitize } from './sanitizer';\nimport { generateFingerprint } from './fingerprint';\nimport { createRateLimiter, type RateLimiter } from './rate-limiter';\nimport { detectEnvironment } from './env-detector';\nimport { buildFixPrompt } from './prompt-builder';\nimport { createTransport } from './transport';\n\nconst SDK_NAME = '@uncaughtdev/core';\nconst SDK_VERSION = '0.1.0';\n\n// ---------------------------------------------------------------------------\n// Module-level singleton\n// ---------------------------------------------------------------------------\n\nlet _client: UncaughtClient | undefined;\n\n/**\n * Initialise the Uncaught SDK. Calling this more than once replaces the\n * previous client instance.\n */\nexport function initUncaught(config: UncaughtConfig): UncaughtClient {\n _client = new UncaughtClient(config);\n return _client;\n}\n\n/**\n * Return the current singleton client, or `undefined` if `initUncaught` has\n * not been called.\n */\nexport function getClient(): UncaughtClient | undefined {\n return _client;\n}\n\n// ---------------------------------------------------------------------------\n// Client class\n// ---------------------------------------------------------------------------\n\nexport class UncaughtClient {\n private readonly config: Required<\n Pick<UncaughtConfig, 'enabled' | 'debug' | 'maxBreadcrumbs' | 'maxEventsPerMinute'>\n > &\n UncaughtConfig;\n\n private readonly breadcrumbs: BreadcrumbStore;\n private readonly transport: Transport;\n private readonly rateLimiter: RateLimiter;\n private readonly sessionId: string;\n private user: UserInfo | undefined;\n\n constructor(config: UncaughtConfig) {\n this.config = {\n enabled: true,\n debug: false,\n maxBreadcrumbs: 20,\n maxEventsPerMinute: 30,\n ...config,\n };\n\n this.breadcrumbs = createBreadcrumbStore(this.config.maxBreadcrumbs);\n this.transport = createTransport(this.config);\n this.rateLimiter = createRateLimiter(this.config.maxEventsPerMinute);\n this.sessionId = generateUUID();\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Capture an error and send it through the transport pipeline.\n *\n * @returns The event ID, or `undefined` if the event was dropped.\n */\n captureError(\n error: unknown,\n context?: {\n request?: RequestInfo;\n operation?: OperationInfo;\n componentStack?: string;\n level?: SeverityLevel;\n }\n ): string | undefined {\n try {\n if (!this.config.enabled) return undefined;\n\n // --- Normalise error -------------------------------------------------\n const errorInfo = normaliseError(error);\n\n if (context?.componentStack) {\n errorInfo.componentStack = context.componentStack;\n }\n\n // --- Check ignoreErrors ----------------------------------------------\n if (this.shouldIgnore(errorInfo.message)) {\n this.debugLog('Event ignored by ignoreErrors filter');\n return undefined;\n }\n\n // --- Fingerprint -----------------------------------------------------\n const fingerprint = generateFingerprint(errorInfo);\n\n // --- Rate limit ------------------------------------------------------\n if (!this.rateLimiter.shouldAllow(fingerprint)) {\n this.debugLog(`Rate-limited: ${fingerprint}`);\n return undefined;\n }\n\n // --- Collect breadcrumbs ---------------------------------------------\n const crumbs = this.breadcrumbs.getAll();\n\n // --- Detect environment ----------------------------------------------\n const environment = detectEnvironment();\n\n // --- Build event -----------------------------------------------------\n const eventId = generateUUID();\n let event: UncaughtEvent = {\n eventId,\n timestamp: isoTimestamp(),\n projectKey: this.config.projectKey,\n level: context?.level ?? 'error',\n fingerprint,\n error: errorInfo,\n breadcrumbs: crumbs,\n request: context?.request,\n operation: context?.operation,\n environment,\n user: this.user\n ? { ...this.user, sessionId: this.sessionId }\n : { sessionId: this.sessionId },\n fixPrompt: '', // will be set below\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n };\n\n // --- Sanitise --------------------------------------------------------\n event = sanitize(event, this.config.sanitizeKeys) as UncaughtEvent;\n\n // --- Build fix prompt ------------------------------------------------\n event.fixPrompt = buildFixPrompt(event);\n\n // --- beforeSend hook -------------------------------------------------\n if (this.config.beforeSend) {\n const result = this.config.beforeSend(event);\n if (result === null) {\n this.debugLog('Event dropped by beforeSend');\n return undefined;\n }\n event = result;\n }\n\n // --- Send ------------------------------------------------------------\n this.transport.send(event);\n this.debugLog(`Captured event: ${eventId} (${fingerprint})`);\n return eventId;\n } catch (err) {\n this.debugLog('captureError failed:', err);\n return undefined;\n }\n }\n\n /**\n * Capture a plain message (not backed by an Error instance).\n */\n captureMessage(\n message: string,\n level: SeverityLevel = 'info'\n ): string | undefined {\n try {\n return this.captureError(new Error(message), { level });\n } catch (err) {\n this.debugLog('captureMessage failed:', err);\n return undefined;\n }\n }\n\n /**\n * Add a breadcrumb to the ring buffer.\n */\n addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'>): void {\n try {\n if (!this.config.enabled) return;\n this.breadcrumbs.add(crumb);\n } catch (err) {\n this.debugLog('addBreadcrumb failed:', err);\n }\n }\n\n /**\n * Set user context that will be attached to subsequent events.\n */\n setUser(user: UserInfo | undefined): void {\n try {\n this.user = user ? { ...user } : undefined;\n } catch (err) {\n this.debugLog('setUser failed:', err);\n }\n }\n\n /**\n * Flush all queued events to the transport.\n */\n async flush(): Promise<void> {\n try {\n await this.transport.flush();\n } catch (err) {\n this.debugLog('flush failed:', err);\n }\n }\n\n // -----------------------------------------------------------------------\n // Internal helpers\n // -----------------------------------------------------------------------\n\n private shouldIgnore(message: string): boolean {\n const patterns = this.config.ignoreErrors;\n if (!patterns || patterns.length === 0) return false;\n\n for (const pattern of patterns) {\n if (typeof pattern === 'string') {\n if (message.includes(pattern)) return true;\n } else if (pattern instanceof RegExp) {\n if (pattern.test(message)) return true;\n }\n }\n\n return false;\n }\n\n private debugLog(...args: unknown[]): void {\n if (this.config.debug) {\n try {\n console.debug('[uncaught]', ...args);\n } catch {\n // Even console.debug can theoretically throw in exotic environments.\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error normalisation\n// ---------------------------------------------------------------------------\n\ninterface NormalisedError {\n message: string;\n type: string;\n stack?: string;\n componentStack?: string;\n raw?: unknown;\n}\n\nfunction normaliseError(error: unknown): NormalisedError {\n if (error instanceof Error) {\n return {\n message: error.message || String(error),\n type: error.constructor?.name || error.name || 'Error',\n stack: error.stack,\n raw: error,\n };\n }\n\n if (typeof error === 'string') {\n return {\n message: error,\n type: 'StringError',\n stack: new Error(error).stack,\n raw: error,\n };\n }\n\n if (error !== null && typeof error === 'object') {\n const obj = error as Record<string, unknown>;\n return {\n message: String(obj.message ?? obj.reason ?? JSON.stringify(error)),\n type: String(obj.name ?? obj.type ?? 'ObjectError'),\n stack: typeof obj.stack === 'string' ? obj.stack : undefined,\n raw: error,\n };\n }\n\n return {\n message: String(error),\n type: 'UnknownError',\n raw: error,\n };\n}\n"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {c,b,a}from'./chunk-P6JRN5CN.mjs';export{a as generateUUID,c as isoTimestamp,b as safeStringify,d as truncate}from'./chunk-P6JRN5CN.mjs';function S(e=20){let t=new Array(e),r=0,n=0;return {add(o){let c$1={...o,timestamp:c()};t[r]=c$1,r=(r+1)%e,n<e&&n++;},getAll(){if(n===0)return [];let o=[],c=(r-n+e)%e;for(let i=0;i<n;i++){let s=(c+i)%e,u=t[s];u&&o.push({...u});}return o},getLast(o){if(o<=0||n===0)return [];let c=Math.min(o,n),i=[];for(let s=0;s<c;s++){let u=(r-1-s+e)%e,d=t[u];d&&i.unshift({...d});}return i},clear(){t.fill(void 0),r=0,n=0;}}}var M=["password","passwd","secret","token","apikey","api_key","authorization","credit_card","creditcard","card_number","cvv","ssn","social_security","private_key","access_token","refresh_token","session_id","cookie"],$=new Set(["authorization","cookie","set-cookie"]),C="[REDACTED]",j=2048;function D(e=[]){let r=[...M,...e].map(n=>n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"));return new RegExp(r.join("|"),"i")}function k(e,t){let r=D(t),n=new WeakSet;function a(o,c){if(c&&r.test(c))return C;if(o==null)return o;if(typeof o=="string")return o.length>j?o.slice(0,j)+"...[truncated]":o;if(typeof o=="number"||typeof o=="boolean")return o;if(typeof o=="bigint")return o.toString();if(!(typeof o=="function"||typeof o=="symbol")){if(o instanceof Date)return o.toISOString();if(Array.isArray(o)){if(n.has(o))return "[Circular]";n.add(o);let i=o.map(s=>a(s));return n.delete(o),i}if(typeof o=="object"){if(n.has(o))return "[Circular]";n.add(o);let i={};for(let s of Object.keys(o)){if($.has(s.toLowerCase())){i[s]=C;continue}i[s]=a(o[s],s);}return n.delete(o),i}return o}}return a(e)}function v(e){let t=N(e.message??""),r=V(e.stack??"",3),n=[e.type??"Error",t,...r].join(`
|
|
2
|
+
`);return z(n)}function N(e){return e.replace(/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,"<UUID>").replace(/\b[0-9a-f]{8,}\b/gi,"<HEX>").replace(/\b\d{4,}\b/g,"<NUM>").replace(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}[.\d]*Z?/g,"<TIMESTAMP>").replace(/([/\\])[a-zA-Z0-9_-]+[-.]([a-f0-9]{6,})\.(js|ts|mjs|cjs|jsx|tsx)/g,"$1<FILE>.$3").trim()}function V(e,t){if(!e)return [];let r=e.split(`
|
|
3
|
+
`),n=[];for(let a of r){if(n.length>=t)break;let o=a.trim(),c=o.match(/at\s+(?:(.+?)\s+\()?(?:(.+?):\d+:\d+)\)?/);if(c){let s=c[1]||"<anonymous>",u=B(c[2]||"<unknown>");n.push(`${u}:${s}`);continue}let i=o.match(/^(.+?)@(.+?):\d+:\d+/);if(i){let s=i[1]||"<anonymous>",u=B(i[2]||"<unknown>");n.push(`${u}:${s}`);continue}}return n}function B(e){return e.replace(/[?#].*$/,"").replace(/^.*\/node_modules\//,"node_modules/").replace(/^(https?:\/\/[^/]+)/,"").replace(/^.*[/\\]/,"")}function z(e){let t=5381;for(let r=0;r<e.length;r++)t=(t<<5)+t+e.charCodeAt(r)|0;return (t>>>0).toString(16).padStart(8,"0")}function x(e=30,t=5){let r=new Map,n=[];function a(o,c){let i=c-6e4,s=0;for(;s<o.length&&o[s]<=i;)s++;return s>0&&o.splice(0,s),o}return {shouldAllow(o){let c=Date.now();if(n=a(n,c),n.length>=e)return false;let i=r.get(o);if(i||(i=[],r.set(o,i)),a(i,c),i.length>=t)return false;if(n.push(c),i.push(c),r.size>1e3)for(let[s,u]of r)u.length===0&&r.delete(s);return true}}}var I;function P(){if(I)return I;let e={};try{let t=typeof window<"u"&&typeof document<"u";if(typeof process<"u"&&process.versions!=null&&process.versions.node!=null)e.runtime="node",e.runtimeVersion=process.versions.node,e.platform=process.platform,e.os=W();else if(t){e.runtime="browser",e.platform="web";let n=navigator?.userAgent??"",a=K(n);e.browser=a.name,e.browserVersion=a.version,e.os=X(n),e.deviceType=q(),e.url=location?.href,e.locale=navigator?.language,e.timezone=Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone;}G(e);}catch{}return I=e,e}function W(){try{let e=process.platform;return {darwin:"macOS",win32:"Windows",linux:"Linux",freebsd:"FreeBSD",sunos:"SunOS"}[e]??e}catch{return}}function K(e){let t=[{name:"Edge",regex:/Edg(?:e|A|iOS)?\/(\d+[\d.]*)/},{name:"Opera",regex:/(?:OPR|Opera)\/(\d+[\d.]*)/},{name:"Samsung Internet",regex:/SamsungBrowser\/(\d+[\d.]*)/},{name:"UC Browser",regex:/UCBrowser\/(\d+[\d.]*)/},{name:"Firefox",regex:/Firefox\/(\d+[\d.]*)/},{name:"Chrome",regex:/Chrome\/(\d+[\d.]*)/},{name:"Safari",regex:/Version\/(\d+[\d.]*).*Safari/}];for(let{name:r,regex:n}of t){let a=e.match(n);if(a)return {name:r,version:a[1]}}return {}}function X(e){if(/Windows/i.test(e))return "Windows";if(/Mac OS X|macOS/i.test(e))return "macOS";if(/Android/i.test(e))return "Android";if(/iPhone|iPad|iPod/i.test(e))return "iOS";if(/Linux/i.test(e))return "Linux";if(/CrOS/i.test(e))return "ChromeOS"}function q(){try{if(typeof window>"u")return;let e=window.screen?.width??window.innerWidth;return e<=480?"mobile":e<=1024?"tablet":"desktop"}catch{return}}function G(e){try{typeof window<"u"&&(window.__NEXT_DATA__?(e.framework="next",e.frameworkVersion=window.__NEXT_DATA__?.buildId??void 0):window.__remixContext?e.framework="remix":window.__NUXT__&&(e.framework="nuxt")),typeof process<"u"&&process.env!=null&&(e.framework||(process.env.__NEXT_PRIVATE_ORIGIN!==void 0||process.env.NEXT_RUNTIME?e.framework="next":process.env.REMIX_DEV_ORIGIN!==void 0&&(e.framework="remix")),process.env.VERCEL?e.platform=e.platform??"vercel":process.env.RAILWAY_PROJECT_ID?e.platform=e.platform??"railway":process.env.FLY_APP_NAME?e.platform=e.platform??"fly":process.env.AWS_LAMBDA_FUNCTION_NAME?e.platform=e.platform??"aws-lambda":process.env.GOOGLE_CLOUD_PROJECT&&(e.platform=e.platform??"gcp"));try{typeof import.meta?.env?.VITE_USER_NODE_ENV<"u"&&(e.framework||(e.framework="vite"));}catch{}}catch{}}function T(e){let t=[];if(t.push(`I have a production bug in my application that I need help diagnosing and fixing.
|
|
4
|
+
`),e.error){let r=J(e.error.stack),n=["## Error",""];n.push(`- **Type:** ${e.error.type||"Error"}`),n.push(`- **Message:** ${e.error.message||"(no message)"}`),r&&n.push(`- **Location:** ${r}`),t.push(n.join(`
|
|
5
|
+
`));}if(e.error?.stack){let r=e.error.stack.split(`
|
|
6
|
+
`).slice(0,15).map(n=>n.trimEnd()).join(`
|
|
7
|
+
`);t.push(`## Stack Trace
|
|
8
|
+
|
|
9
|
+
\`\`\`
|
|
10
|
+
${r}
|
|
11
|
+
\`\`\``);}return e.operation&&t.push(H(e.operation)),e.request&&t.push(Y(e.request)),e.breadcrumbs&&e.breadcrumbs.length>0&&t.push(Z(e.breadcrumbs)),e.environment&&t.push(ee(e.environment)),e.error?.componentStack&&t.push(`## React Component Stack
|
|
12
|
+
|
|
13
|
+
\`\`\`
|
|
14
|
+
${e.error.componentStack.trim()}
|
|
15
|
+
\`\`\``),t.push(["## What I need","","1. **Root cause analysis** \u2014 explain why this error is occurring.","2. **A fix** \u2014 provide the corrected code with an explanation of the changes.","3. **Prevention** \u2014 suggest any guards or tests to prevent this from happening again."].join(`
|
|
16
|
+
`)),t.join(`
|
|
17
|
+
|
|
18
|
+
`)+`
|
|
19
|
+
`}function J(e){if(e)for(let t of e.split(`
|
|
20
|
+
`)){let r=t.trim(),n=r.match(/at\s+(?:.+?\s+\()?(.+?:\d+:\d+)\)?/);if(n)return n[1];let a=r.match(/@(.+?:\d+:\d+)/);if(a)return a[1]}}function H(e){let t=["## Failed Operation",""];return t.push(`- **Provider:** ${e.provider}`),t.push(`- **Type:** ${e.type}`),t.push(`- **Method:** ${e.method}`),e.params&&(t.push("- **Params:**"),t.push("```json"),t.push(JSON.stringify(e.params,null,2)),t.push("```")),e.errorCode&&t.push(`- **Error Code:** ${e.errorCode}`),e.errorDetails&&t.push(`- **Error Details:** ${e.errorDetails}`),t.join(`
|
|
21
|
+
`)}function Y(e){let t=["## HTTP Request Context",""];return e.method&&t.push(`- **Method:** ${e.method}`),e.url&&t.push(`- **URL:** ${e.url}`),e.body&&(t.push("- **Body:**"),t.push("```json"),t.push(typeof e.body=="string"?e.body:JSON.stringify(e.body,null,2)),t.push("```")),t.join(`
|
|
22
|
+
`)}function Z(e){let t=e.slice(-5),r=["## User Session",""];for(let n of t){let a=Q(n.timestamp);r.push(`- \`${a}\` **[${n.type}]** ${n.message}`);}return r.join(`
|
|
23
|
+
`)}function Q(e){try{let t=new Date(e),r=String(t.getHours()).padStart(2,"0"),n=String(t.getMinutes()).padStart(2,"0"),a=String(t.getSeconds()).padStart(2,"0");return `${r}:${n}:${a}`}catch{return e}}function ee(e){let t=["## Environment",""],r=[["Framework",e.framework],["Framework Version",e.frameworkVersion],["Runtime",e.runtime],["Runtime Version",e.runtimeVersion],["Platform",e.platform],["Browser",e.browser?`${e.browser} ${e.browserVersion??""}`.trim():void 0],["OS",e.os],["Device",e.deviceType],["Locale",e.locale],["Timezone",e.timezone],["URL",e.url]];for(let[n,a]of r)a&&t.push(`- **${n}:** ${a}`);return t.join(`
|
|
24
|
+
`)}function _(e){switch(e.transport??"local"){case "console":return F();case "remote":return ie(e);default:return te(e)}}function F(e){return {send(t){try{let r=`[uncaught] ${t.error.type}: ${t.error.message}`;typeof console.group=="function"?console.group(r):console.log(`--- ${r} ---`),console.error("Error:",t.error.message),t.error.stack&&console.log("Stack:",t.error.stack),console.log("Event ID:",t.eventId),console.log("Fingerprint:",t.fingerprint),console.log("Breadcrumbs:",t.breadcrumbs),t.fixPrompt&&console.log(`Fix Prompt:
|
|
25
|
+
`,t.fixPrompt),typeof console.groupEnd=="function"&&console.groupEnd();}catch{}},async flush(){}}}function te(e){return typeof process<"u"&&process.versions?.node!=null?ne(e):oe()}function ne(e){let t,r,n="",a=false;async function o(){if(a)return;let i=await import('fs/promises'),s=await import('path');t=i,r=s,n=e.localOutputDir??r.resolve(process.cwd(),".uncaught"),await t.mkdir(r.join(n,"events"),{recursive:true}),await t.mkdir(r.join(n,"fix-prompts"),{recursive:true}),await c(t,r),a=true;}async function c(i,s){try{let u=s.resolve(process.cwd(),".gitignore"),d="";try{d=await i.readFile(u,"utf-8");}catch{}d.includes(".uncaught")||await i.appendFile(u,`
|
|
26
|
+
# Uncaught local error store
|
|
27
|
+
.uncaught/
|
|
28
|
+
`);}catch{}}return {async send(i){try{if(await o(),!t||!r)return;let s=i.fingerprint,u=r.join(n,"events",s);await t.mkdir(u,{recursive:!0});let m=`event-${i.timestamp.replace(/[:.]/g,"-")}.json`,y=r.join(u,m),f=y+".tmp";await t.writeFile(f,b(i),"utf-8"),await t.rename(f,y);let p=r.join(u,"latest.json"),l=p+".tmp";await t.writeFile(l,b(i),"utf-8"),await t.rename(l,p);let b$1=`${s}.md`,L=r.join(n,"fix-prompts",b$1),O=L+".tmp";await t.writeFile(O,i.fixPrompt,"utf-8"),await t.rename(O,L),await re(t,r,n,i,m,b$1);}catch{}},async flush(){}}}async function re(e,t,r,n,a,o){let c=t.join(r,"issues.json"),i=[];try{let m=await e.readFile(c,"utf-8");i=JSON.parse(m);}catch{}let s=i.find(m=>m.fingerprint===n.fingerprint),u=n.user?.id??n.user?.email??"anonymous";s?(s.count+=1,s.lastSeen=n.timestamp,s.latestEventFile=a,s.fixPromptFile=o,s.affectedUsers.includes(u)||s.affectedUsers.push(u),s.status==="resolved"&&(s.status="open")):i.push({fingerprint:n.fingerprint,title:n.error.message,errorType:n.error.type,count:1,affectedUsers:[u],firstSeen:n.timestamp,lastSeen:n.timestamp,status:"open",fixPromptFile:o,latestEventFile:a});let d=c+".tmp";await e.writeFile(d,JSON.stringify(i,null,2),"utf-8"),await e.rename(d,c);}function oe(e){let t=[],r=F();async function n(a){try{let o=await fetch("/api/uncaught/local",{method:"POST",headers:{"Content-Type":"application/json"},body:b({events:a})});return o.ok||o.status===202}catch{return false}}return {send(a){t.push(a),n([a]).then(o=>{o||r.send(a);}).catch(()=>{r.send(a);});},async flush(){if(t.length===0)return;let a=t.splice(0,t.length);if(!await n(a))for(let c of a)r.send(c);}}}function ie(e){let t=e.endpoint??"",r=e.projectKey??"",n=3,a=10,o=5e3,c=[],i,s=false,u=[1e3,2e3,4e3];async function d(f){if(!(f.length===0||s))for(let p=0;p<=n;p++)try{let l=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json",...r?{"X-Project-Key":r}:{}},body:b({events:f})});if(l.ok||l.status===202)return;if(l.status===401){s=!0,i&&clearInterval(i);return}if(l.status===429){let b=parseInt(l.headers?.get?.("Retry-After")??"10",10);await U(b*1e3);continue}p<n&&await U(u[p]??4e3);}catch{p<n&&await U(u[p]??4e3);}}function m(){i||(i=setInterval(()=>{if(c.length>0){let f=c.splice(0,a);d(f).catch(()=>{});}},o),typeof i=="object"&&"unref"in i&&i.unref());}function y(){try{typeof window<"u"&&typeof navigator?.sendBeacon=="function"&&(window.addEventListener("visibilitychange",()=>{if(document.visibilityState==="hidden"&&c.length>0){let f=b({events:c.splice(0,c.length)});navigator.sendBeacon(t,f);}}),window.addEventListener("pagehide",()=>{if(c.length>0){let f=b({events:c.splice(0,c.length)});navigator.sendBeacon(t,f);}}));}catch{}}return m(),y(),{send(f){if(!s&&(c.push(f),c.length>=a)){let p=c.splice(0,a);d(p).catch(()=>{});}},async flush(){for(i&&(clearInterval(i),i=void 0);c.length>0;){let f=c.splice(0,a);await d(f);}}}}function U(e){return new Promise(t=>setTimeout(t,e))}var se="@uncaughtdev/core",ae="0.1.0",R;function ce(e){return R=new E(e),R}function ue(){return R}var E=class{constructor(t){this.config={enabled:true,debug:false,maxBreadcrumbs:20,maxEventsPerMinute:30,...t},this.breadcrumbs=S(this.config.maxBreadcrumbs),this.transport=_(this.config),this.rateLimiter=x(this.config.maxEventsPerMinute),this.sessionId=a();}captureError(t,r){try{if(!this.config.enabled)return;let n=fe(t);if(r?.componentStack&&(n.componentStack=r.componentStack),this.shouldIgnore(n.message)){this.debugLog("Event ignored by ignoreErrors filter");return}let a$1=v(n);if(!this.rateLimiter.shouldAllow(a$1)){this.debugLog(`Rate-limited: ${a$1}`);return}let o=this.breadcrumbs.getAll(),c$1=P(),i=a(),s={eventId:i,timestamp:c(),projectKey:this.config.projectKey,level:r?.level??"error",fingerprint:a$1,error:n,breadcrumbs:o,request:r?.request,operation:r?.operation,environment:c$1,user:this.user?{...this.user,sessionId:this.sessionId}:{sessionId:this.sessionId},fixPrompt:"",sdk:{name:se,version:ae}};if(s=k(s,this.config.sanitizeKeys),s.fixPrompt=T(s),this.config.beforeSend){let u=this.config.beforeSend(s);if(u===null){this.debugLog("Event dropped by beforeSend");return}s=u;}return this.transport.send(s),this.debugLog(`Captured event: ${i} (${a$1})`),i}catch(n){this.debugLog("captureError failed:",n);return}}captureMessage(t,r="info"){try{return this.captureError(new Error(t),{level:r})}catch(n){this.debugLog("captureMessage failed:",n);return}}addBreadcrumb(t){try{if(!this.config.enabled)return;this.breadcrumbs.add(t);}catch(r){this.debugLog("addBreadcrumb failed:",r);}}setUser(t){try{this.user=t?{...t}:void 0;}catch(r){this.debugLog("setUser failed:",r);}}async flush(){try{await this.transport.flush();}catch(t){this.debugLog("flush failed:",t);}}shouldIgnore(t){let r=this.config.ignoreErrors;if(!r||r.length===0)return false;for(let n of r)if(typeof n=="string"){if(t.includes(n))return true}else if(n instanceof RegExp&&n.test(t))return true;return false}debugLog(...t){if(this.config.debug)try{console.debug("[uncaught]",...t);}catch{}}};function fe(e){if(e instanceof Error)return {message:e.message||String(e),type:e.constructor?.name||e.name||"Error",stack:e.stack,raw:e};if(typeof e=="string")return {message:e,type:"StringError",stack:new Error(e).stack,raw:e};if(e!==null&&typeof e=="object"){let t=e;return {message:String(t.message??t.reason??JSON.stringify(e)),type:String(t.name??t.type??"ObjectError"),stack:typeof t.stack=="string"?t.stack:void 0,raw:e}}return {message:String(e),type:"UnknownError",raw:e}}export{E as UncaughtClient,T as buildFixPrompt,S as createBreadcrumbStore,x as createRateLimiter,_ as createTransport,P as detectEnvironment,v as generateFingerprint,ue as getClient,ce as initUncaught,k as sanitize};//# sourceMappingURL=index.mjs.map
|
|
29
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/breadcrumbs.ts","../src/sanitizer.ts","../src/fingerprint.ts","../src/rate-limiter.ts","../src/env-detector.ts","../src/prompt-builder.ts","../src/transport.ts","../src/client.ts"],"names":["createBreadcrumbStore","capacity","buffer","head","size","crumb","entry","isoTimestamp","result","start","idx","n","count","i","DEFAULT_SENSITIVE_KEYS","SENSITIVE_HEADERS","REDACTED","MAX_STRING_LENGTH","buildKeyPattern","additionalKeys","escaped","k","sanitize","obj","pattern","seen","walk","value","key","item","generateFingerprint","error","normalisedMessage","normaliseMessage","frames","extractTopFrames","input","djb2","msg","stack","lines","line","trimmed","v8Match","fn","file","normalisePath","smMatch","p","str","hash","createRateLimiter","globalMax","perFingerprintMax","buckets","globalTimestamps","prune","timestamps","now","cutoff","fingerprint","fpTimestamps","ts","cached","detectEnvironment","info","isBrowser","detectNodeOS","ua","browserInfo","parseBrowserUA","parseOS","detectDeviceType","detectFramework","platform","patterns","name","regex","match","width","buildFixPrompt","event","sections","location","extractLocation","l","formatOperation","formatRequest","formatBreadcrumbs","formatEnvironment","v8","sm","op","req","crumbs","recent","time","formatTime","iso","d","h","m","s","env","entries","label","createTransport","config","createConsoleTransport","createRemoteTransport","createLocalTransport","_config","title","createLocalFileTransport","createLocalClientTransport","fsPromises","pathModule","baseDir","initialised","init","fs","path","ensureGitignore","gitignorePath","content","fp","eventDir","eventFile","eventPath","tmpEventPath","safeStringify","latestPath","tmpLatestPath","promptFile","promptPath","tmpPromptPath","updateIssuesIndex","indexPath","issues","raw","existing","userId","tmpIndexPath","queue","consoleFallback","postEvents","events","res","ok","batch","endpoint","projectKey","maxRetries","batchSize","flushIntervalMs","flushTimer","stopped","backoffDelays","sendBatch","attempt","retryAfter","sleep","startFlushing","registerBeacon","payload","ms","resolve","SDK_NAME","SDK_VERSION","_client","initUncaught","UncaughtClient","getClient","generateUUID","context","errorInfo","normaliseError","environment","eventId","err","message","level","user","args"],"mappings":"gJAgBO,SAASA,CAAAA,CAAsBC,EAAmB,EAAA,CAAqB,CAC5E,IAAMC,CAAAA,CAAwC,IAAI,KAAA,CAAMD,CAAQ,CAAA,CAC5DE,CAAAA,CAAO,EACPC,CAAAA,CAAO,CAAA,CA8DX,OA5D+B,CAC7B,GAAA,CAAIC,EAA4C,CAC9C,IAAMC,GAAAA,CAAoB,CACxB,GAAGD,CAAAA,CACH,UAAWE,CAAAA,EACb,EAEAL,CAAAA,CAAOC,CAAI,EAAIG,GAAAA,CACfH,CAAAA,CAAAA,CAAQA,CAAAA,CAAO,CAAA,EAAKF,CAAAA,CAEhBG,CAAAA,CAAOH,GACTG,CAAAA,GAEJ,CAAA,CAEA,QAAuB,CACrB,GAAIA,IAAS,CAAA,CAAG,OAAO,EAAC,CAExB,IAAMI,CAAAA,CAAuB,EAAC,CAGxBC,CAAAA,CAAAA,CAASN,EAAOC,CAAAA,CAAOH,CAAAA,EAAYA,EAEzC,IAAA,IAAS,CAAA,CAAI,CAAA,CAAG,CAAA,CAAIG,CAAAA,CAAM,CAAA,EAAA,CAAK,CAC7B,IAAMM,CAAAA,CAAAA,CAAOD,EAAQ,CAAA,EAAKR,CAAAA,CACpBK,EAAQJ,CAAAA,CAAOQ,CAAG,CAAA,CACpBJ,CAAAA,EAEFE,CAAAA,CAAO,IAAA,CAAK,CAAE,GAAGF,CAAM,CAAC,EAE5B,CAEA,OAAOE,CACT,CAAA,CAEA,OAAA,CAAQG,CAAAA,CAAyB,CAC/B,GAAIA,GAAK,CAAA,EAAKP,CAAAA,GAAS,CAAA,CAAG,OAAO,EAAC,CAElC,IAAMQ,CAAAA,CAAQ,IAAA,CAAK,GAAA,CAAID,CAAAA,CAAGP,CAAI,CAAA,CACxBI,EAAuB,EAAC,CAG9B,QAASK,CAAAA,CAAI,CAAA,CAAGA,EAAID,CAAAA,CAAOC,CAAAA,EAAAA,CAAK,CAC9B,IAAMH,CAAAA,CAAAA,CAAOP,CAAAA,CAAO,EAAIU,CAAAA,CAAIZ,CAAAA,EAAYA,EAClCK,CAAAA,CAAQJ,CAAAA,CAAOQ,CAAG,CAAA,CACpBJ,CAAAA,EACFE,CAAAA,CAAO,OAAA,CAAQ,CAAE,GAAGF,CAAM,CAAC,EAE/B,CAEA,OAAOE,CACT,EAEA,KAAA,EAAc,CACZN,CAAAA,CAAO,IAAA,CAAK,MAAS,CAAA,CACrBC,EAAO,CAAA,CACPC,CAAAA,CAAO,EACT,CACF,CAGF,CC7EA,IAAMU,CAAAA,CAAmC,CACvC,UAAA,CACA,QAAA,CACA,QAAA,CACA,OAAA,CACA,SACA,SAAA,CACA,eAAA,CACA,cACA,YAAA,CACA,aAAA,CACA,MACA,KAAA,CACA,iBAAA,CACA,aAAA,CACA,cAAA,CACA,eAAA,CACA,YAAA,CACA,QACF,CAAA,CAGMC,CAAAA,CAAoB,IAAI,GAAA,CAAI,CAAC,gBAAiB,QAAA,CAAU,YAAY,CAAC,CAAA,CAErEC,CAAAA,CAAW,YAAA,CACXC,EAAoB,IAAA,CAM1B,SAASC,EAAgBC,CAAAA,CAA2B,GAAY,CAG9D,IAAMC,CAAAA,CAFM,CAAC,GAAGN,CAAAA,CAAwB,GAAGK,CAAc,CAAA,CAErC,GAAA,CAAKE,CAAAA,EAAMA,CAAAA,CAAE,OAAA,CAAQ,sBAAuB,MAAM,CAAC,CAAA,CACvE,OAAO,IAAI,MAAA,CAAOD,EAAQ,IAAA,CAAK,GAAG,EAAG,GAAG,CAC1C,CAaO,SAASE,CAAAA,CAAYC,CAAAA,CAAQJ,CAAAA,CAA8B,CAChE,IAAMK,EAAUN,CAAAA,CAAgBC,CAAc,EACxCM,CAAAA,CAAO,IAAI,QAEjB,SAASC,CAAAA,CAAKC,CAAAA,CAAgBC,CAAAA,CAAuB,CAEnD,GAAIA,GAAOJ,CAAAA,CAAQ,IAAA,CAAKI,CAAG,CAAA,CACzB,OAAOZ,EAIT,GAAIW,CAAAA,EAAU,IAAA,CAA6B,OAAOA,CAAAA,CAElD,GAAI,OAAOA,CAAAA,EAAU,QAAA,CACnB,OAAOA,CAAAA,CAAM,MAAA,CAASV,CAAAA,CAClBU,EAAM,KAAA,CAAM,CAAA,CAAGV,CAAiB,CAAA,CAAI,gBAAA,CACpCU,CAAAA,CAGN,GAAI,OAAOA,CAAAA,EAAU,UAAY,OAAOA,CAAAA,EAAU,UAChD,OAAOA,CAAAA,CAGT,GAAI,OAAOA,CAAAA,EAAU,QAAA,CACnB,OAAOA,CAAAA,CAAM,QAAA,GAGf,GAAI,EAAA,OAAOA,GAAU,UAAA,EAAc,OAAOA,CAAAA,EAAU,QAAA,CAAA,CAKpD,CAAA,GAAIA,CAAAA,YAAiB,KACnB,OAAOA,CAAAA,CAAM,aAAY,CAI3B,GAAI,MAAM,OAAA,CAAQA,CAAK,CAAA,CAAG,CACxB,GAAIF,CAAAA,CAAK,IAAIE,CAAK,CAAA,CAAG,OAAO,YAAA,CAC5BF,CAAAA,CAAK,GAAA,CAAIE,CAAK,CAAA,CACd,IAAMnB,CAAAA,CAASmB,CAAAA,CAAM,GAAA,CAAKE,CAAAA,EAASH,EAAKG,CAAI,CAAC,EAC7C,OAAAJ,CAAAA,CAAK,OAAOE,CAAK,CAAA,CACVnB,CACT,CAGA,GAAI,OAAOmB,GAAU,QAAA,CAAU,CAC7B,GAAIF,CAAAA,CAAK,GAAA,CAAIE,CAAe,CAAA,CAAG,OAAO,YAAA,CACtCF,CAAAA,CAAK,GAAA,CAAIE,CAAe,EAExB,IAAMnB,CAAAA,CAAkC,EAAC,CAEzC,IAAA,IAAWa,KAAK,MAAA,CAAO,IAAA,CAAKM,CAAgC,CAAA,CAAG,CAE7D,GAAIZ,EAAkB,GAAA,CAAIM,CAAAA,CAAE,WAAA,EAAa,CAAA,CAAG,CAC1Cb,EAAOa,CAAC,CAAA,CAAIL,CAAAA,CACZ,QACF,CAEAR,CAAAA,CAAOa,CAAC,CAAA,CAAIK,CAAAA,CAAMC,EAAkCN,CAAC,CAAA,CAAGA,CAAC,EAC3D,CAEA,OAAAI,CAAAA,CAAK,MAAA,CAAOE,CAAe,EACpBnB,CACT,CAEA,OAAOmB,CAAAA,CACT,CAEA,OAAOD,CAAAA,CAAKH,CAAG,CACjB,CC9GO,SAASO,CAAAA,CAAoBC,EAIzB,CACT,IAAMC,EAAoBC,CAAAA,CAAiBF,CAAAA,CAAM,SAAW,EAAE,CAAA,CACxDG,CAAAA,CAASC,CAAAA,CAAiBJ,CAAAA,CAAM,KAAA,EAAS,GAAI,CAAC,CAAA,CAC9CK,CAAAA,CAAQ,CAACL,CAAAA,CAAM,IAAA,EAAQ,QAASC,CAAAA,CAAmB,GAAGE,CAAM,CAAA,CAAE,IAAA,CAClE;AAAA,CACF,CAAA,CACA,OAAOG,CAAAA,CAAKD,CAAK,CACnB,CAUA,SAASH,CAAAA,CAAiBK,CAAAA,CAAqB,CAC7C,OACEA,EAEG,OAAA,CACC,gEAAA,CACA,QACF,CAAA,CAEC,OAAA,CAAQ,qBAAsB,OAAO,CAAA,CAErC,OAAA,CAAQ,aAAA,CAAe,OAAO,CAAA,CAE9B,QACC,8CAAA,CACA,aACF,EAEC,OAAA,CACC,mEAAA,CACA,aACF,CAAA,CACC,IAAA,EAEP,CAOA,SAASH,CAAAA,CAAiBI,EAAe3B,CAAAA,CAAyB,CAChE,GAAI,CAAC2B,CAAAA,CAAO,OAAO,EAAC,CAEpB,IAAMC,CAAAA,CAAQD,CAAAA,CAAM,KAAA,CAAM;AAAA,CAAI,EACxBL,CAAAA,CAAmB,EAAC,CAE1B,IAAA,IAAWO,KAAQD,CAAAA,CAAO,CACxB,GAAIN,CAAAA,CAAO,QAAUtB,CAAAA,CAAO,MAE5B,IAAM8B,CAAAA,CAAUD,CAAAA,CAAK,MAAK,CAIpBE,CAAAA,CAAUD,CAAAA,CAAQ,KAAA,CACtB,0CACF,CAAA,CACA,GAAIC,EAAS,CACX,IAAMC,EAAKD,CAAAA,CAAQ,CAAC,CAAA,EAAK,aAAA,CACnBE,EAAOC,CAAAA,CAAcH,CAAAA,CAAQ,CAAC,CAAA,EAAK,WAAW,EACpDT,CAAAA,CAAO,IAAA,CAAK,CAAA,EAAGW,CAAI,IAAID,CAAE,CAAA,CAAE,CAAA,CAC3B,QACF,CAGA,IAAMG,CAAAA,CAAUL,CAAAA,CAAQ,KAAA,CAAM,sBAAsB,CAAA,CACpD,GAAIK,EAAS,CACX,IAAMH,EAAKG,CAAAA,CAAQ,CAAC,CAAA,EAAK,aAAA,CACnBF,EAAOC,CAAAA,CAAcC,CAAAA,CAAQ,CAAC,CAAA,EAAK,WAAW,EACpDb,CAAAA,CAAO,IAAA,CAAK,CAAA,EAAGW,CAAI,IAAID,CAAE,CAAA,CAAE,EAC3B,QACF,CACF,CAEA,OAAOV,CACT,CAMA,SAASY,EAAcE,CAAAA,CAAmB,CACxC,OAAOA,CAAAA,CACJ,QAAQ,SAAA,CAAW,EAAE,CAAA,CACrB,OAAA,CAAQ,sBAAuB,eAAe,CAAA,CAC9C,QAAQ,qBAAA,CAAuB,EAAE,EACjC,OAAA,CAAQ,UAAA,CAAY,EAAE,CAC3B,CAKA,SAASX,CAAAA,CAAKY,EAAqB,CACjC,IAAIC,EAAO,IAAA,CACX,IAAA,IAASrC,CAAAA,CAAI,CAAA,CAAGA,EAAIoC,CAAAA,CAAI,MAAA,CAAQpC,IAE9BqC,CAAAA,CAAAA,CAASA,CAAAA,EAAQ,GAAKA,CAAAA,CAAOD,CAAAA,CAAI,UAAA,CAAWpC,CAAC,EAAK,CAAA,CAGpD,OAAA,CAAQqC,CAAAA,GAAS,CAAA,EAAG,SAAS,EAAE,CAAA,CAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAClD,CCpGO,SAASC,CAAAA,CACdC,CAAAA,CAAoB,GACpBC,CAAAA,CAA4B,CAAA,CACf,CAEb,IAAMC,EAAU,IAAI,GAAA,CAEhBC,EAA6B,EAAC,CAMlC,SAASC,CAAAA,CAAMC,CAAAA,CAAsBC,CAAAA,CAAuB,CAC1D,IAAMC,CAAAA,CAASD,CAAAA,CAAM,IAEjBjD,CAAAA,CAAQ,CAAA,CACZ,KAAOA,CAAAA,CAAQgD,CAAAA,CAAW,MAAA,EAAUA,CAAAA,CAAWhD,CAAK,CAAA,EAAKkD,CAAAA,EACvDlD,CAAAA,EAAAA,CAEF,OAAIA,EAAQ,CAAA,EACVgD,CAAAA,CAAW,MAAA,CAAO,CAAA,CAAGhD,CAAK,CAAA,CAErBgD,CACT,CAEA,OAAO,CACL,YAAYG,CAAAA,CAA8B,CACxC,IAAMF,CAAAA,CAAM,KAAK,GAAA,EAAI,CAIrB,GADAH,CAAAA,CAAmBC,CAAAA,CAAMD,EAAkBG,CAAG,CAAA,CAC1CH,CAAAA,CAAiB,MAAA,EAAUH,EAC7B,OAAO,MAAA,CAIT,IAAIS,CAAAA,CAAeP,CAAAA,CAAQ,IAAIM,CAAW,CAAA,CAO1C,GANKC,CAAAA,GACHA,EAAe,EAAC,CAChBP,CAAAA,CAAQ,GAAA,CAAIM,EAAaC,CAAY,CAAA,CAAA,CAEvCL,CAAAA,CAAMK,CAAAA,CAAcH,CAAG,CAAA,CAEnBG,CAAAA,CAAa,QAAUR,CAAAA,CACzB,OAAO,OAQT,GAJAE,CAAAA,CAAiB,IAAA,CAAKG,CAAG,EACzBG,CAAAA,CAAa,IAAA,CAAKH,CAAG,CAAA,CAGjBJ,CAAAA,CAAQ,KAAO,GAAA,CACjB,IAAA,GAAW,CAAC1B,CAAAA,CAAKkC,CAAE,CAAA,GAAKR,CAAAA,CAClBQ,EAAG,MAAA,GAAW,CAAA,EAChBR,EAAQ,MAAA,CAAO1B,CAAG,CAAA,CAKxB,OAAO,KACT,CACF,CACF,CClFA,IAAImC,EAQG,SAASC,CAAAA,EAAqC,CACnD,GAAID,EAAQ,OAAOA,CAAAA,CAEnB,IAAME,CAAAA,CAAwB,GAE9B,GAAI,CACF,IAAMC,CAAAA,CACJ,OAAO,MAAA,CAAW,GAAA,EAAe,OAAO,QAAA,CAAa,GAAA,CAOvD,GALE,OAAO,OAAA,CAAY,GAAA,EACnB,OAAA,CAAQ,UAAY,IAAA,EACpB,OAAA,CAAQ,SAAS,IAAA,EAAQ,IAAA,CAIzBD,EAAK,OAAA,CAAU,MAAA,CACfA,CAAAA,CAAK,cAAA,CAAiB,QAAQ,QAAA,CAAS,IAAA,CACvCA,EAAK,QAAA,CAAW,OAAA,CAAQ,SACxBA,CAAAA,CAAK,EAAA,CAAKE,CAAAA,EAAa,CAAA,KAAA,GACdD,EAAW,CACpBD,CAAAA,CAAK,QAAU,SAAA,CACfA,CAAAA,CAAK,SAAW,KAAA,CAEhB,IAAMG,CAAAA,CAAK,SAAA,EAAW,WAAa,EAAA,CAC7BC,CAAAA,CAAcC,EAAeF,CAAE,CAAA,CACrCH,EAAK,OAAA,CAAUI,CAAAA,CAAY,IAAA,CAC3BJ,CAAAA,CAAK,eAAiBI,CAAAA,CAAY,OAAA,CAClCJ,EAAK,EAAA,CAAKM,CAAAA,CAAQH,CAAE,CAAA,CACpBH,CAAAA,CAAK,UAAA,CAAaO,CAAAA,GAClBP,CAAAA,CAAK,GAAA,CAAM,QAAA,EAAU,IAAA,CACrBA,EAAK,MAAA,CAAS,SAAA,EAAW,QAAA,CACzBA,CAAAA,CAAK,SAAW,IAAA,EAAM,cAAA,MAAoB,eAAA,IAAkB,EAAG,SACjE,CAGAQ,CAAAA,CAAgBR,CAAI,EACtB,MAAQ,CAER,CAEA,OAAAF,CAAAA,CAASE,CAAAA,CACFA,CACT,CAaA,SAASE,CAAAA,EAAmC,CAC1C,GAAI,CACF,IAAMO,EAAW,OAAA,CAAQ,QAAA,CAQzB,OAPoC,CAClC,MAAA,CAAQ,OAAA,CACR,KAAA,CAAO,UACP,KAAA,CAAO,OAAA,CACP,OAAA,CAAS,SAAA,CACT,MAAO,OACT,CAAA,CACWA,CAAQ,CAAA,EAAKA,CAC1B,CAAA,KAAQ,CACN,MACF,CACF,CAOA,SAASJ,CAAAA,CAAeF,CAAAA,CAAyB,CAE/C,IAAMO,EAAmD,CACvD,CAAE,KAAM,MAAA,CAAQ,KAAA,CAAO,8BAA+B,CAAA,CACtD,CAAE,IAAA,CAAM,OAAA,CAAS,MAAO,4BAA6B,CAAA,CACrD,CAAE,IAAA,CAAM,kBAAA,CAAoB,MAAO,6BAA8B,CAAA,CACjE,CAAE,IAAA,CAAM,aAAc,KAAA,CAAO,wBAAyB,CAAA,CACtD,CAAE,KAAM,SAAA,CAAW,KAAA,CAAO,sBAAuB,CAAA,CACjD,CAAE,IAAA,CAAM,QAAA,CAAU,MAAO,qBAAsB,CAAA,CAC/C,CAAE,IAAA,CAAM,QAAA,CAAU,KAAA,CAAO,8BAA+B,CAC1D,CAAA,CAEA,IAAA,GAAW,CAAE,IAAA,CAAAC,CAAAA,CAAM,MAAAC,CAAM,CAAA,GAAKF,CAAAA,CAAU,CACtC,IAAMG,CAAAA,CAAQV,CAAAA,CAAG,MAAMS,CAAK,CAAA,CAC5B,GAAIC,CAAAA,CACF,OAAO,CAAE,IAAA,CAAAF,EAAM,OAAA,CAASE,CAAAA,CAAM,CAAC,CAAE,CAErC,CAEA,OAAO,EACT,CAEA,SAASP,CAAAA,CAAQH,EAAgC,CAC/C,GAAI,WAAW,IAAA,CAAKA,CAAE,CAAA,CAAG,OAAO,UAChC,GAAI,iBAAA,CAAkB,KAAKA,CAAE,CAAA,CAAG,OAAO,OAAA,CACvC,GAAI,UAAA,CAAW,IAAA,CAAKA,CAAE,CAAA,CAAG,OAAO,UAChC,GAAI,mBAAA,CAAoB,KAAKA,CAAE,CAAA,CAAG,OAAO,KAAA,CACzC,GAAI,QAAA,CAAS,IAAA,CAAKA,CAAE,CAAA,CAAG,OAAO,OAAA,CAC9B,GAAI,OAAA,CAAQ,IAAA,CAAKA,CAAE,CAAA,CAAG,OAAO,UAE/B,CAEA,SAASI,GAAuC,CAC9C,GAAI,CACF,GAAI,OAAO,MAAA,CAAW,GAAA,CAAa,OAEnC,IAAMO,CAAAA,CAAQ,OAAO,MAAA,EAAQ,KAAA,EAAS,MAAA,CAAO,UAAA,CAE7C,OAAIA,CAAAA,EAAS,GAAA,CAAY,SACrBA,CAAAA,EAAS,IAAA,CAAa,SACnB,SACT,CAAA,KAAQ,CACN,MACF,CACF,CAEA,SAASN,CAAAA,CAAgBR,CAAAA,CAA6B,CACpD,GAAI,CAEE,OAAO,MAAA,CAAW,MAEf,MAAA,CAAe,aAAA,EAClBA,EAAK,SAAA,CAAY,MAAA,CACjBA,EAAK,gBAAA,CACF,MAAA,CAAe,aAAA,EAAe,OAAA,EAAW,QAGpC,MAAA,CAAe,cAAA,CACvBA,EAAK,SAAA,CAAY,OAAA,CAGT,OAAe,QAAA,GACvBA,CAAAA,CAAK,SAAA,CAAY,MAAA,CAAA,CAAA,CAMnB,OAAO,OAAA,CAAY,GAAA,EACnB,QAAQ,GAAA,EAAO,IAAA,GAGVA,EAAK,SAAA,GACJ,OAAA,CAAQ,GAAA,CAAI,qBAAA,GAA0B,QAAa,OAAA,CAAQ,GAAA,CAAI,YAAA,CACjEA,CAAAA,CAAK,UAAY,MAAA,CACR,OAAA,CAAQ,GAAA,CAAI,gBAAA,GAAqB,SAC1CA,CAAAA,CAAK,SAAA,CAAY,UAKjB,OAAA,CAAQ,GAAA,CAAI,OACdA,CAAAA,CAAK,QAAA,CAAWA,CAAAA,CAAK,QAAA,EAAY,SACxB,OAAA,CAAQ,GAAA,CAAI,mBACrBA,CAAAA,CAAK,QAAA,CAAWA,EAAK,QAAA,EAAY,SAAA,CACxB,OAAA,CAAQ,GAAA,CAAI,aACrBA,CAAAA,CAAK,QAAA,CAAWA,EAAK,QAAA,EAAY,KAAA,CACxB,QAAQ,GAAA,CAAI,wBAAA,CACrBA,CAAAA,CAAK,QAAA,CAAWA,EAAK,QAAA,EAAY,YAAA,CACxB,QAAQ,GAAA,CAAI,oBAAA,GACrBA,EAAK,QAAA,CAAWA,CAAAA,CAAK,QAAA,EAAY,KAAA,CAAA,CAAA,CAKrC,GAAI,CACE,OAAQ,aAAqB,GAAA,EAAK,kBAAA,CAAuB,MACtDA,CAAAA,CAAK,SAAA,GACRA,CAAAA,CAAK,SAAA,CAAY,SAGvB,CAAA,KAAQ,CAER,CACF,CAAA,KAAQ,CAER,CACF,CC1LO,SAASe,CAAAA,CAAeC,CAAAA,CAAuC,CACpE,IAAMC,CAAAA,CAAqB,EAAC,CAQ5B,GALAA,EAAS,IAAA,CACP,CAAA;AAAA,CACF,CAAA,CAGID,EAAM,KAAA,CAAO,CACf,IAAME,CAAAA,CAAWC,CAAAA,CAAgBH,EAAM,KAAA,CAAM,KAAK,EAC5CzC,CAAAA,CAAkB,CAAC,WAAY,EAAE,CAAA,CACvCA,EAAM,IAAA,CAAK,CAAA,YAAA,EAAeyC,EAAM,KAAA,CAAM,IAAA,EAAQ,OAAO,CAAA,CAAE,CAAA,CACvDzC,EAAM,IAAA,CAAK,CAAA,eAAA,EAAkByC,EAAM,KAAA,CAAM,OAAA,EAAW,cAAc,CAAA,CAAE,CAAA,CAChEE,GACF3C,CAAAA,CAAM,IAAA,CAAK,mBAAmB2C,CAAQ,CAAA,CAAE,EAE1CD,CAAAA,CAAS,IAAA,CAAK1C,EAAM,IAAA,CAAK;AAAA,CAAI,CAAC,EAChC,CAGA,GAAIyC,CAAAA,CAAM,KAAA,EAAO,KAAA,CAAO,CACtB,IAAM/C,CAAAA,CAAS+C,CAAAA,CAAM,KAAA,CAAM,MACxB,KAAA,CAAM;AAAA,CAAI,CAAA,CACV,KAAA,CAAM,CAAA,CAAG,EAAE,CAAA,CACX,GAAA,CAAKI,CAAAA,EAAMA,CAAAA,CAAE,OAAA,EAAS,CAAA,CACtB,IAAA,CAAK;AAAA,CAAI,CAAA,CACZH,EAAS,IAAA,CAAK,CAAA;;AAAA;AAAA,EAA6BhD,CAAM;AAAA,MAAA,CAAU,EAC7D,CAGA,OAAI+C,CAAAA,CAAM,WACRC,CAAAA,CAAS,IAAA,CAAKI,EAAgBL,CAAAA,CAAM,SAAS,CAAC,CAAA,CAI5CA,CAAAA,CAAM,SACRC,CAAAA,CAAS,IAAA,CAAKK,EAAcN,CAAAA,CAAM,OAAO,CAAC,CAAA,CAIxCA,CAAAA,CAAM,WAAA,EAAeA,EAAM,WAAA,CAAY,MAAA,CAAS,GAClDC,CAAAA,CAAS,IAAA,CAAKM,EAAkBP,CAAAA,CAAM,WAAW,CAAC,CAAA,CAIhDA,CAAAA,CAAM,WAAA,EACRC,EAAS,IAAA,CAAKO,EAAAA,CAAkBR,EAAM,WAAW,CAAC,EAIhDA,CAAAA,CAAM,KAAA,EAAO,cAAA,EACfC,CAAAA,CAAS,IAAA,CACP,CAAA;;AAAA;AAAA,EAAuCD,CAAAA,CAAM,KAAA,CAAM,cAAA,CAAe,IAAA,EAAM;AAAA,MAAA,CAC1E,CAAA,CAIFC,CAAAA,CAAS,IAAA,CACP,CACE,gBAAA,CACA,GACA,wEAAA,CACA,oFAAA,CACA,4FACF,CAAA,CAAE,IAAA,CAAK;AAAA,CAAI,CACb,CAAA,CAEOA,CAAAA,CAAS,IAAA,CAAK;;AAAA,CAAM,CAAA,CAAI;AAAA,CACjC,CASA,SAASE,CAAAA,CAAgB7C,CAAAA,CAAoC,CAC3D,GAAKA,CAAAA,CAEL,IAAA,IAAWE,CAAAA,IAAQF,CAAAA,CAAM,KAAA,CAAM;AAAA,CAAI,CAAA,CAAG,CACpC,IAAMG,CAAAA,CAAUD,EAAK,IAAA,EAAK,CAGpBiD,CAAAA,CAAKhD,CAAAA,CAAQ,KAAA,CAAM,oCAAoC,EAC7D,GAAIgD,CAAAA,CAAI,OAAOA,CAAAA,CAAG,CAAC,CAAA,CAGnB,IAAMC,CAAAA,CAAKjD,CAAAA,CAAQ,KAAA,CAAM,gBAAgB,CAAA,CACzC,GAAIiD,EAAI,OAAOA,CAAAA,CAAG,CAAC,CACrB,CAGF,CAEA,SAASL,CAAAA,CAAgBM,CAAAA,CAA2B,CAClD,IAAMpD,CAAAA,CAAkB,CAAC,sBAAuB,EAAE,CAAA,CAClD,OAAAA,CAAAA,CAAM,IAAA,CAAK,CAAA,gBAAA,EAAmBoD,EAAG,QAAQ,CAAA,CAAE,CAAA,CAC3CpD,CAAAA,CAAM,IAAA,CAAK,CAAA,YAAA,EAAeoD,EAAG,IAAI,CAAA,CAAE,CAAA,CACnCpD,CAAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiBoD,EAAG,MAAM,CAAA,CAAE,CAAA,CACnCA,CAAAA,CAAG,MAAA,GACLpD,CAAAA,CAAM,KAAK,eAAe,CAAA,CAC1BA,CAAAA,CAAM,IAAA,CAAK,SAAS,CAAA,CACpBA,EAAM,IAAA,CAAK,IAAA,CAAK,SAAA,CAAUoD,CAAAA,CAAG,MAAA,CAAQ,IAAA,CAAM,CAAC,CAAC,CAAA,CAC7CpD,CAAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAA,CAEdoD,EAAG,SAAA,EACLpD,CAAAA,CAAM,IAAA,CAAK,CAAA,kBAAA,EAAqBoD,CAAAA,CAAG,SAAS,EAAE,CAAA,CAE5CA,CAAAA,CAAG,YAAA,EACLpD,CAAAA,CAAM,IAAA,CAAK,CAAA,qBAAA,EAAwBoD,EAAG,YAAY,CAAA,CAAE,CAAA,CAE/CpD,CAAAA,CAAM,IAAA,CAAK;AAAA,CAAI,CACxB,CAEA,SAAS+C,CAAAA,CAAcM,CAAAA,CAA0B,CAC/C,IAAMrD,CAAAA,CAAkB,CAAC,yBAAA,CAA2B,EAAE,CAAA,CACtD,OAAIqD,CAAAA,CAAI,MAAA,EAAQrD,CAAAA,CAAM,IAAA,CAAK,CAAA,cAAA,EAAiBqD,CAAAA,CAAI,MAAM,CAAA,CAAE,CAAA,CACpDA,CAAAA,CAAI,GAAA,EAAKrD,CAAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAcqD,CAAAA,CAAI,GAAG,CAAA,CAAE,CAAA,CAC3CA,CAAAA,CAAI,IAAA,GACNrD,CAAAA,CAAM,IAAA,CAAK,aAAa,CAAA,CACxBA,CAAAA,CAAM,IAAA,CAAK,SAAS,CAAA,CACpBA,CAAAA,CAAM,IAAA,CACJ,OAAOqD,CAAAA,CAAI,IAAA,EAAS,QAAA,CAChBA,CAAAA,CAAI,IAAA,CACJ,IAAA,CAAK,SAAA,CAAUA,CAAAA,CAAI,IAAA,CAAM,IAAA,CAAM,CAAC,CACtC,CAAA,CACArD,CAAAA,CAAM,IAAA,CAAK,KAAK,CAAA,CAAA,CAEXA,EAAM,IAAA,CAAK;AAAA,CAAI,CACxB,CAEA,SAASgD,EAAkBM,CAAAA,CAA8B,CAEvD,IAAMC,CAAAA,CAASD,CAAAA,CAAO,MAAM,EAAE,CAAA,CACxBtD,EAAkB,CAAC,iBAAA,CAAmB,EAAE,CAAA,CAE9C,IAAA,IAAWnC,KAAS0F,CAAAA,CAAQ,CAC1B,IAAMC,CAAAA,CAAOC,EAAW5F,CAAAA,CAAM,SAAS,EACvCmC,CAAAA,CAAM,IAAA,CAAK,OAAOwD,CAAI,CAAA,MAAA,EAAS3F,EAAM,IAAI,CAAA,IAAA,EAAOA,EAAM,OAAO,CAAA,CAAE,EACjE,CAEA,OAAOmC,EAAM,IAAA,CAAK;AAAA,CAAI,CACxB,CAKA,SAASyD,CAAAA,CAAWC,EAAqB,CACvC,GAAI,CACF,IAAMC,EAAI,IAAI,IAAA,CAAKD,CAAG,CAAA,CAChBE,EAAI,MAAA,CAAOD,CAAAA,CAAE,QAAA,EAAU,EAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAA,CACxCE,EAAI,MAAA,CAAOF,CAAAA,CAAE,UAAA,EAAY,EAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAA,CAC1CG,EAAI,MAAA,CAAOH,CAAAA,CAAE,UAAA,EAAY,EAAE,QAAA,CAAS,CAAA,CAAG,GAAG,CAAA,CAChD,OAAO,CAAA,EAAGC,CAAC,CAAA,CAAA,EAAIC,CAAC,IAAIC,CAAC,CAAA,CACvB,CAAA,KAAQ,CACN,OAAOJ,CACT,CACF,CAEA,SAAST,GAAkBc,CAAAA,CAA8B,CACvD,IAAM/D,CAAAA,CAAkB,CAAC,gBAAA,CAAkB,EAAE,CAAA,CACvCgE,CAAAA,CAA+C,CACnD,CAAC,WAAA,CAAaD,CAAAA,CAAI,SAAS,EAC3B,CAAC,mBAAA,CAAqBA,CAAAA,CAAI,gBAAgB,CAAA,CAC1C,CAAC,SAAA,CAAWA,CAAAA,CAAI,OAAO,CAAA,CACvB,CAAC,iBAAA,CAAmBA,CAAAA,CAAI,cAAc,CAAA,CACtC,CAAC,UAAA,CAAYA,CAAAA,CAAI,QAAQ,CAAA,CACzB,CAAC,SAAA,CAAWA,CAAAA,CAAI,QAAU,CAAA,EAAGA,CAAAA,CAAI,OAAO,CAAA,CAAA,EAAIA,EAAI,cAAA,EAAkB,EAAE,CAAA,CAAA,CAAG,IAAA,GAAS,MAAS,CAAA,CACzF,CAAC,IAAA,CAAMA,EAAI,EAAE,CAAA,CACb,CAAC,QAAA,CAAUA,EAAI,UAAU,CAAA,CACzB,CAAC,QAAA,CAAUA,EAAI,MAAM,CAAA,CACrB,CAAC,UAAA,CAAYA,EAAI,QAAQ,CAAA,CACzB,CAAC,KAAA,CAAOA,EAAI,GAAG,CACjB,CAAA,CAEA,IAAA,GAAW,CAACE,CAAAA,CAAO9E,CAAK,CAAA,GAAK6E,CAAAA,CACvB7E,GACFa,CAAAA,CAAM,IAAA,CAAK,CAAA,IAAA,EAAOiE,CAAK,OAAO9E,CAAK,CAAA,CAAE,CAAA,CAIzC,OAAOa,EAAM,IAAA,CAAK;AAAA,CAAI,CACxB,CCjLO,SAASkE,CAAAA,CAAgBC,EAAmC,CAGjE,OAFaA,CAAAA,CAAO,SAAA,EAAa,OAAA,EAG/B,KAAK,SAAA,CACH,OAAOC,CAAAA,CAA6B,CAAA,CACtC,KAAK,SACH,OAAOC,EAAAA,CAAsBF,CAAM,CAAA,CAErC,QACE,OAAOG,GAAqBH,CAAM,CACtC,CACF,CAMA,SAASC,EAAuBG,CAAAA,CAAoC,CAClE,OAAO,CACL,IAAA,CAAK9B,CAAAA,CAA4B,CAC/B,GAAI,CACF,IAAM+B,CAAAA,CAAQ,CAAA,WAAA,EAAc/B,CAAAA,CAAM,MAAM,IAAI,CAAA,EAAA,EAAKA,CAAAA,CAAM,KAAA,CAAM,OAAO,CAAA,CAAA,CAEhE,OAAO,OAAA,CAAQ,KAAA,EAAU,WAC3B,OAAA,CAAQ,KAAA,CAAM+B,CAAK,CAAA,CAEnB,OAAA,CAAQ,GAAA,CAAI,CAAA,IAAA,EAAOA,CAAK,CAAA,IAAA,CAAM,EAGhC,OAAA,CAAQ,KAAA,CAAM,QAAA,CAAU/B,CAAAA,CAAM,KAAA,CAAM,OAAO,EACvCA,CAAAA,CAAM,KAAA,CAAM,KAAA,EACd,OAAA,CAAQ,GAAA,CAAI,QAAA,CAAUA,EAAM,KAAA,CAAM,KAAK,EAEzC,OAAA,CAAQ,GAAA,CAAI,YAAaA,CAAAA,CAAM,OAAO,CAAA,CACtC,OAAA,CAAQ,GAAA,CAAI,cAAA,CAAgBA,EAAM,WAAW,CAAA,CAC7C,OAAA,CAAQ,GAAA,CAAI,cAAA,CAAgBA,CAAAA,CAAM,WAAW,CAAA,CAEzCA,CAAAA,CAAM,SAAA,EACR,OAAA,CAAQ,GAAA,CAAI,CAAA;AAAA,CAAA,CAAiBA,CAAAA,CAAM,SAAS,CAAA,CAG1C,OAAO,QAAQ,QAAA,EAAa,UAAA,EAC9B,OAAA,CAAQ,QAAA,GAEZ,CAAA,KAAQ,CAER,CACF,CAAA,CAEA,MAAM,KAAA,EAAuB,CAE7B,CACF,CACF,CAaA,SAAS6B,EAAAA,CAAqBH,CAAAA,CAAmC,CAI/D,OAFiB,OAAO,OAAA,CAAY,GAAA,EAAe,OAAA,CAAQ,UAAU,IAAA,EAAQ,IAAA,CAGpEM,EAAAA,CAAyBN,CAAM,EAGjCO,EAAAA,CAAiC,CAC1C,CAoBA,SAASD,EAAAA,CAAyBN,CAAAA,CAAmC,CACnE,IAAIQ,CAAAA,CACAC,CAAAA,CACAC,CAAAA,CAAkB,EAAA,CAClBC,EAAc,KAAA,CAElB,eAAeC,CAAAA,EAAsB,CACnC,GAAID,CAAAA,CAAa,OAIjB,IAAME,CAAAA,CAAK,MAAM,OAAO,aAAa,CAAA,CAC/BC,CAAAA,CAAO,MAAM,OAAO,MAAM,CAAA,CAChCN,CAAAA,CAAaK,EACbJ,CAAAA,CAAaK,CAAAA,CAEbJ,CAAAA,CAAUV,CAAAA,CAAO,gBAAkBS,CAAAA,CAAW,OAAA,CAAQ,OAAA,CAAQ,GAAA,EAAI,CAAG,WAAW,CAAA,CAGhF,MAAMD,EAAW,KAAA,CAAMC,CAAAA,CAAW,IAAA,CAAKC,CAAAA,CAAS,QAAQ,CAAA,CAAG,CAAE,SAAA,CAAW,IAAK,CAAC,CAAA,CAC9E,MAAMF,CAAAA,CAAW,KAAA,CAAMC,EAAW,IAAA,CAAKC,CAAAA,CAAS,aAAa,CAAA,CAAG,CAAE,SAAA,CAAW,IAAK,CAAC,CAAA,CAGnF,MAAMK,CAAAA,CAAgBP,CAAAA,CAAYC,CAAU,CAAA,CAE5CE,EAAc,KAChB,CAEA,eAAeI,CAAAA,CAAgBF,CAAAA,CAAcC,CAAAA,CAAiC,CAC5E,GAAI,CACF,IAAME,CAAAA,CAAgBF,CAAAA,CAAK,OAAA,CAAQ,QAAQ,GAAA,EAAI,CAAG,YAAY,CAAA,CAC1DG,EAAU,EAAA,CACd,GAAI,CACFA,CAAAA,CAAU,MAAMJ,CAAAA,CAAG,QAAA,CAASG,CAAAA,CAAe,OAAO,EACpD,CAAA,KAAQ,CAER,CAEKC,CAAAA,CAAQ,SAAS,WAAW,CAAA,EAE/B,MAAMJ,CAAAA,CAAG,WAAWG,CAAAA,CADP;AAAA;AAAA;AAAA,CAC0B,EAE3C,CAAA,KAAQ,CAER,CACF,CAEA,OAAO,CACL,MAAM,IAAA,CAAK1C,EAAqC,CAC9C,GAAI,CAEF,GADA,MAAMsC,CAAAA,EAAK,CACP,CAACJ,CAAAA,EAAc,CAACC,CAAAA,CAAY,OAEhC,IAAMS,CAAAA,CAAK5C,EAAM,WAAA,CACX6C,CAAAA,CAAWV,CAAAA,CAAW,IAAA,CAAKC,EAAS,QAAA,CAAUQ,CAAE,CAAA,CACtD,MAAMV,EAAW,KAAA,CAAMW,CAAAA,CAAU,CAAE,SAAA,CAAW,EAAK,CAAC,CAAA,CAIpD,IAAMC,CAAAA,CAAY,SADP9C,CAAAA,CAAM,SAAA,CAAU,OAAA,CAAQ,OAAA,CAAS,GAAG,CAClB,CAAA,KAAA,CAAA,CACvB+C,CAAAA,CAAYZ,CAAAA,CAAW,KAAKU,CAAAA,CAAUC,CAAS,CAAA,CAC/CE,CAAAA,CAAeD,EAAY,MAAA,CACjC,MAAMb,CAAAA,CAAW,SAAA,CAAUc,EAAcC,CAAAA,CAAcjD,CAAK,CAAA,CAAG,OAAO,EACtE,MAAMkC,CAAAA,CAAW,MAAA,CAAOc,CAAAA,CAAcD,CAAS,CAAA,CAG/C,IAAMG,CAAAA,CAAaf,CAAAA,CAAW,KAAKU,CAAAA,CAAU,aAAa,CAAA,CACpDM,CAAAA,CAAgBD,EAAa,MAAA,CACnC,MAAMhB,CAAAA,CAAW,SAAA,CAAUiB,EAAeF,CAAAA,CAAcjD,CAAK,CAAA,CAAG,OAAO,EACvE,MAAMkC,CAAAA,CAAW,MAAA,CAAOiB,CAAAA,CAAeD,CAAU,CAAA,CAGjD,IAAME,GAAAA,CAAa,CAAA,EAAGR,CAAE,CAAA,GAAA,CAAA,CAClBS,CAAAA,CAAalB,CAAAA,CAAW,IAAA,CAAKC,EAAS,aAAA,CAAegB,GAAU,CAAA,CAC/DE,CAAAA,CAAgBD,EAAa,MAAA,CACnC,MAAMnB,CAAAA,CAAW,SAAA,CAAUoB,EAAetD,CAAAA,CAAM,SAAA,CAAW,OAAO,CAAA,CAClE,MAAMkC,CAAAA,CAAW,MAAA,CAAOoB,CAAAA,CAAeD,CAAU,EAGjD,MAAME,EAAAA,CACJrB,CAAAA,CACAC,CAAAA,CACAC,EACApC,CAAAA,CACA8C,CAAAA,CACAM,GACF,EACF,MAAQ,CAER,CACF,CAAA,CAEA,MAAM,OAAuB,CAE7B,CACF,CACF,CAKA,eAAeG,EAAAA,CACbhB,CAAAA,CACAC,CAAAA,CACAJ,CAAAA,CACApC,EACA8C,CAAAA,CACAM,CAAAA,CACe,CACf,IAAMI,CAAAA,CAAYhB,CAAAA,CAAK,IAAA,CAAKJ,CAAAA,CAAS,aAAa,CAAA,CAE9CqB,CAAAA,CAAuB,EAAC,CAC5B,GAAI,CACF,IAAMC,CAAAA,CAAM,MAAMnB,EAAG,QAAA,CAASiB,CAAAA,CAAW,OAAO,CAAA,CAChDC,EAAS,IAAA,CAAK,KAAA,CAAMC,CAAG,EACzB,MAAQ,CAER,CAEA,IAAMC,CAAAA,CAAWF,EAAO,IAAA,CAAM7H,CAAAA,EAAMA,CAAAA,CAAE,WAAA,GAAgBoE,EAAM,WAAW,CAAA,CACjE4D,CAAAA,CAAS5D,CAAAA,CAAM,MAAM,EAAA,EAAMA,CAAAA,CAAM,IAAA,EAAM,KAAA,EAAS,YAElD2D,CAAAA,EACFA,CAAAA,CAAS,KAAA,EAAS,CAAA,CAClBA,EAAS,QAAA,CAAW3D,CAAAA,CAAM,SAAA,CAC1B2D,CAAAA,CAAS,gBAAkBb,CAAAA,CAC3Ba,CAAAA,CAAS,aAAA,CAAgBP,CAAAA,CACpBO,EAAS,aAAA,CAAc,QAAA,CAASC,CAAM,CAAA,EACzCD,EAAS,aAAA,CAAc,IAAA,CAAKC,CAAM,CAAA,CAGhCD,EAAS,MAAA,GAAW,UAAA,GACtBA,CAAAA,CAAS,MAAA,CAAS,SAGpBF,CAAAA,CAAO,IAAA,CAAK,CACV,WAAA,CAAazD,EAAM,WAAA,CACnB,KAAA,CAAOA,CAAAA,CAAM,KAAA,CAAM,QACnB,SAAA,CAAWA,CAAAA,CAAM,KAAA,CAAM,IAAA,CACvB,MAAO,CAAA,CACP,aAAA,CAAe,CAAC4D,CAAM,EACtB,SAAA,CAAW5D,CAAAA,CAAM,SAAA,CACjB,QAAA,CAAUA,EAAM,SAAA,CAChB,MAAA,CAAQ,MAAA,CACR,aAAA,CAAeoD,EACf,eAAA,CAAiBN,CACnB,CAAC,CAAA,CAGH,IAAMe,CAAAA,CAAeL,CAAAA,CAAY,MAAA,CACjC,MAAMjB,EAAG,SAAA,CAAUsB,CAAAA,CAAc,IAAA,CAAK,SAAA,CAAUJ,EAAQ,IAAA,CAAM,CAAC,CAAA,CAAG,OAAO,EACzE,MAAMlB,CAAAA,CAAG,MAAA,CAAOsB,CAAAA,CAAcL,CAAS,EACzC,CAMA,SAASvB,EAAAA,CAA2BH,EAAoC,CACtE,IAAMgC,CAAAA,CAAyB,GACzBC,CAAAA,CAAkBpC,CAAAA,CAA8B,CAAA,CAEtD,eAAeqC,CAAAA,CAAWC,CAAAA,CAA2C,CACnE,GAAI,CACF,IAAMC,CAAAA,CAAM,MAAM,KAAA,CAAM,sBAAuB,CAC7C,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CAAE,cAAA,CAAgB,kBAAmB,CAAA,CAC9C,KAAMjB,CAAAA,CAAc,CAAE,MAAA,CAAAgB,CAAO,CAAC,CAChC,CAAC,CAAA,CAED,OAAOC,EAAI,EAAA,EAAMA,CAAAA,CAAI,MAAA,GAAW,GAClC,MAAQ,CACN,OAAO,MACT,CACF,CAEA,OAAO,CACL,IAAA,CAAKlE,CAAAA,CAA4B,CAC/B8D,CAAAA,CAAM,IAAA,CAAK9D,CAAK,CAAA,CAGhBgE,EAAW,CAAChE,CAAK,CAAC,CAAA,CAAE,KAAMmE,CAAAA,EAAO,CAC1BA,CAAAA,EAEHJ,CAAAA,CAAgB,KAAK/D,CAAK,EAE9B,CAAC,CAAA,CAAE,MAAM,IAAM,CACb+D,CAAAA,CAAgB,IAAA,CAAK/D,CAAK,EAC5B,CAAC,EACH,CAAA,CAEA,MAAM,KAAA,EAAuB,CAC3B,GAAI8D,CAAAA,CAAM,SAAW,CAAA,CAAG,OAExB,IAAMM,CAAAA,CAAQN,EAAM,MAAA,CAAO,CAAA,CAAGA,CAAAA,CAAM,MAAM,EAE1C,GAAI,CADO,MAAME,CAAAA,CAAWI,CAAK,CAAA,CAG/B,IAAA,IAAWpE,CAAAA,IAASoE,CAAAA,CAClBL,EAAgB,IAAA,CAAK/D,CAAK,EAGhC,CACF,CACF,CAMA,SAAS4B,EAAAA,CAAsBF,CAAAA,CAAmC,CAChE,IAAM2C,CAAAA,CAAW3C,CAAAA,CAAO,QAAA,EAAY,GAC9B4C,CAAAA,CAAa5C,CAAAA,CAAO,UAAA,EAAc,EAAA,CAClC6C,EAAa,CAAA,CACbC,CAAAA,CAAY,EAAA,CACZC,CAAAA,CAAkB,IAElBX,CAAAA,CAAyB,EAAC,CAC5BY,CAAAA,CACAC,EAAU,KAAA,CAGRC,CAAAA,CAAgB,CAAC,GAAA,CAAM,IAAM,GAAI,CAAA,CAEvC,eAAeC,CAAAA,CAAUZ,EAAwC,CAC/D,GAAI,EAAAA,CAAAA,CAAO,SAAW,CAAA,EAAKU,CAAAA,CAAAA,CAE3B,IAAA,IAASG,CAAAA,CAAU,EAAGA,CAAAA,EAAWP,CAAAA,CAAYO,CAAAA,EAAAA,CAC3C,GAAI,CACF,IAAMZ,CAAAA,CAAM,MAAM,KAAA,CAAMG,EAAU,CAChC,MAAA,CAAQ,MAAA,CACR,OAAA,CAAS,CACP,cAAA,CAAgB,kBAAA,CAChB,GAAIC,CAAAA,CAAa,CAAE,eAAA,CAAiBA,CAAW,CAAA,CAAI,EACrD,CAAA,CACA,IAAA,CAAMrB,CAAAA,CAAc,CAAE,OAAAgB,CAAO,CAAC,CAChC,CAAC,EAED,GAAIC,CAAAA,CAAI,EAAA,EAAMA,CAAAA,CAAI,SAAW,GAAA,CAC3B,OAGF,GAAIA,CAAAA,CAAI,SAAW,GAAA,CAAK,CAEtBS,CAAAA,CAAU,CAAA,CAAA,CACND,GAAY,aAAA,CAAcA,CAAU,CAAA,CACxC,MACF,CAEA,GAAIR,CAAAA,CAAI,MAAA,GAAW,GAAA,CAAK,CAEtB,IAAMa,CAAAA,CAAa,QAAA,CACjBb,CAAAA,CAAI,SAAS,GAAA,GAAM,aAAa,CAAA,EAAK,IAAA,CACrC,EACF,CAAA,CACA,MAAMc,CAAAA,CAAMD,CAAAA,CAAa,GAAI,CAAA,CAC7B,QACF,CAGID,CAAAA,CAAUP,GACZ,MAAMS,CAAAA,CAAMJ,CAAAA,CAAcE,CAAO,GAAK,GAAI,EAE9C,CAAA,KAAQ,CAEFA,EAAUP,CAAAA,EACZ,MAAMS,CAAAA,CAAMJ,CAAAA,CAAcE,CAAO,CAAA,EAAK,GAAI,EAE9C,CAGJ,CAEA,SAASG,CAAAA,EAAsB,CACzBP,CAAAA,GACJA,EAAa,WAAA,CAAY,IAAM,CAC7B,GAAIZ,EAAM,MAAA,CAAS,CAAA,CAAG,CACpB,IAAMM,EAAQN,CAAAA,CAAM,MAAA,CAAO,CAAA,CAAGU,CAAS,EACvCK,CAAAA,CAAUT,CAAK,CAAA,CAAE,KAAA,CAAM,IAAM,CAE7B,CAAC,EACH,CACF,EAAGK,CAAe,CAAA,CAGd,OAAOC,CAAAA,EAAe,UAAY,OAAA,GAAWA,CAAAA,EAC9CA,CAAAA,CAAqC,KAAA,IAE1C,CAGA,SAASQ,CAAAA,EAAuB,CAC9B,GAAI,CAEA,OAAO,MAAA,CAAW,GAAA,EAClB,OAAO,SAAA,EAAW,UAAA,EAAe,UAAA,GAEjC,MAAA,CAAO,iBAAiB,kBAAA,CAAoB,IAAM,CAChD,GAAI,SAAS,eAAA,GAAoB,QAAA,EAAYpB,CAAAA,CAAM,MAAA,CAAS,EAAG,CAC7D,IAAMqB,CAAAA,CAAUlC,CAAAA,CAAc,CAAE,MAAA,CAAQa,CAAAA,CAAM,MAAA,CAAO,CAAA,CAAGA,EAAM,MAAM,CAAE,CAAC,CAAA,CACvE,UAAU,UAAA,CAAWO,CAAAA,CAAUc,CAAO,EACxC,CACF,CAAC,CAAA,CAED,MAAA,CAAO,iBAAiB,UAAA,CAAY,IAAM,CACxC,GAAIrB,EAAM,MAAA,CAAS,CAAA,CAAG,CACpB,IAAMqB,EAAUlC,CAAAA,CAAc,CAAE,MAAA,CAAQa,CAAAA,CAAM,OAAO,CAAA,CAAGA,CAAAA,CAAM,MAAM,CAAE,CAAC,CAAA,CACvE,SAAA,CAAU,UAAA,CAAWO,CAAAA,CAAUc,CAAO,EACxC,CACF,CAAC,CAAA,EAEL,MAAQ,CAER,CACF,CAEA,OAAAF,GAAc,CACdC,CAAAA,EAAe,CAER,CACL,KAAKlF,CAAAA,CAA4B,CAC/B,GAAI,CAAA2E,IAEJb,CAAAA,CAAM,IAAA,CAAK9D,CAAK,CAAA,CAGZ8D,EAAM,MAAA,EAAUU,CAAAA,CAAAA,CAAW,CAC7B,IAAMJ,EAAQN,CAAAA,CAAM,MAAA,CAAO,CAAA,CAAGU,CAAS,EACvCK,CAAAA,CAAUT,CAAK,CAAA,CAAE,KAAA,CAAM,IAAM,CAE7B,CAAC,EACH,CACF,EAEA,MAAM,KAAA,EAAuB,CAM3B,IALIM,IACF,aAAA,CAAcA,CAAU,CAAA,CACxBA,CAAAA,CAAa,QAGRZ,CAAAA,CAAM,MAAA,CAAS,CAAA,EAAG,CACvB,IAAMM,CAAAA,CAAQN,CAAAA,CAAM,MAAA,CAAO,CAAA,CAAGU,CAAS,CAAA,CACvC,MAAMK,CAAAA,CAAUT,CAAK,EACvB,CACF,CACF,CACF,CAMA,SAASY,CAAAA,CAAMI,CAAAA,CAA2B,CACxC,OAAO,IAAI,OAAA,CAASC,CAAAA,EAAY,UAAA,CAAWA,CAAAA,CAASD,CAAE,CAAC,CACzD,CC5bA,IAAME,GAAW,mBAAA,CACXC,EAAAA,CAAc,OAAA,CAMhBC,CAAAA,CAMG,SAASC,EAAAA,CAAa/D,CAAAA,CAAwC,CACnE,OAAA8D,EAAU,IAAIE,CAAAA,CAAehE,CAAM,CAAA,CAC5B8D,CACT,CAMO,SAASG,EAAAA,EAAwC,CACtD,OAAOH,CACT,CAMO,IAAME,CAAAA,CAAN,KAAqB,CAY1B,WAAA,CAAYhE,CAAAA,CAAwB,CAClC,KAAK,MAAA,CAAS,CACZ,OAAA,CAAS,IAAA,CACT,MAAO,KAAA,CACP,cAAA,CAAgB,EAAA,CAChB,kBAAA,CAAoB,GACpB,GAAGA,CACL,CAAA,CAEA,IAAA,CAAK,YAAc3G,CAAAA,CAAsB,IAAA,CAAK,MAAA,CAAO,cAAc,EACnE,IAAA,CAAK,SAAA,CAAY0G,CAAAA,CAAgB,IAAA,CAAK,MAAM,CAAA,CAC5C,IAAA,CAAK,WAAA,CAAcvD,CAAAA,CAAkB,KAAK,MAAA,CAAO,kBAAkB,CAAA,CACnE,IAAA,CAAK,UAAY0H,CAAAA,GACnB,CAWA,YAAA,CACE9I,EACA+I,CAAAA,CAMoB,CACpB,GAAI,CACF,GAAI,CAAC,IAAA,CAAK,MAAA,CAAO,OAAA,CAAS,OAG1B,IAAMC,CAAAA,CAAYC,EAAAA,CAAejJ,CAAK,EAOtC,GALI+I,CAAAA,EAAS,cAAA,GACXC,CAAAA,CAAU,eAAiBD,CAAAA,CAAQ,cAAA,CAAA,CAIjC,IAAA,CAAK,YAAA,CAAaC,EAAU,OAAO,CAAA,CAAG,CACxC,IAAA,CAAK,SAAS,sCAAsC,CAAA,CACpD,MACF,CAGA,IAAMnH,GAAAA,CAAc9B,CAAAA,CAAoBiJ,CAAS,CAAA,CAGjD,GAAI,CAAC,IAAA,CAAK,WAAA,CAAY,WAAA,CAAYnH,GAAW,CAAA,CAAG,CAC9C,IAAA,CAAK,QAAA,CAAS,iBAAiBA,GAAW,CAAA,CAAE,CAAA,CAC5C,MACF,CAGA,IAAMkC,CAAAA,CAAS,IAAA,CAAK,WAAA,CAAY,QAAO,CAGjCmF,GAAAA,CAAcjH,CAAAA,EAAkB,CAGhCkH,EAAUL,CAAAA,EAAa,CACzB5F,CAAAA,CAAuB,CACzB,QAAAiG,CAAAA,CACA,SAAA,CAAW3K,CAAAA,EAAa,CACxB,WAAY,IAAA,CAAK,MAAA,CAAO,UAAA,CACxB,KAAA,CAAOuK,GAAS,KAAA,EAAS,OAAA,CACzB,WAAA,CAAAlH,GAAAA,CACA,MAAOmH,CAAAA,CACP,WAAA,CAAajF,CAAAA,CACb,OAAA,CAASgF,GAAS,OAAA,CAClB,SAAA,CAAWA,CAAAA,EAAS,SAAA,CACpB,YAAAG,GAAAA,CACA,IAAA,CAAM,IAAA,CAAK,IAAA,CACP,CAAE,GAAG,IAAA,CAAK,IAAA,CAAM,SAAA,CAAW,KAAK,SAAU,CAAA,CAC1C,CAAE,SAAA,CAAW,KAAK,SAAU,CAAA,CAChC,SAAA,CAAW,EAAA,CACX,IAAK,CAAE,IAAA,CAAMV,EAAAA,CAAU,OAAA,CAASC,EAAY,CAC9C,CAAA,CASA,GANAvF,CAAAA,CAAQ3D,EAAS2D,CAAAA,CAAO,IAAA,CAAK,MAAA,CAAO,YAAY,CAAA,CAGhDA,CAAAA,CAAM,SAAA,CAAYD,CAAAA,CAAeC,CAAK,CAAA,CAGlC,IAAA,CAAK,MAAA,CAAO,UAAA,CAAY,CAC1B,IAAMzE,CAAAA,CAAS,IAAA,CAAK,MAAA,CAAO,WAAWyE,CAAK,CAAA,CAC3C,GAAIzE,CAAAA,GAAW,KAAM,CACnB,IAAA,CAAK,QAAA,CAAS,6BAA6B,EAC3C,MACF,CACAyE,CAAAA,CAAQzE,EACV,CAGA,OAAA,IAAA,CAAK,SAAA,CAAU,IAAA,CAAKyE,CAAK,EACzB,IAAA,CAAK,QAAA,CAAS,CAAA,gBAAA,EAAmBiG,CAAO,KAAKtH,GAAW,CAAA,CAAA,CAAG,CAAA,CACpDsH,CACT,OAASC,CAAAA,CAAK,CACZ,IAAA,CAAK,QAAA,CAAS,uBAAwBA,CAAG,CAAA,CACzC,MACF,CACF,CAKA,cAAA,CACEC,CAAAA,CACAC,CAAAA,CAAuB,MAAA,CACH,CACpB,GAAI,CACF,OAAO,IAAA,CAAK,aAAa,IAAI,KAAA,CAAMD,CAAO,CAAA,CAAG,CAAE,KAAA,CAAAC,CAAM,CAAC,CACxD,OAASF,CAAAA,CAAK,CACZ,IAAA,CAAK,QAAA,CAAS,yBAA0BA,CAAG,CAAA,CAC3C,MACF,CACF,CAKA,aAAA,CAAc9K,CAAAA,CAA4C,CACxD,GAAI,CACF,GAAI,CAAC,IAAA,CAAK,MAAA,CAAO,QAAS,OAC1B,IAAA,CAAK,WAAA,CAAY,GAAA,CAAIA,CAAK,EAC5B,CAAA,MAAS8K,CAAAA,CAAK,CACZ,KAAK,QAAA,CAAS,uBAAA,CAAyBA,CAAG,EAC5C,CACF,CAKA,OAAA,CAAQG,CAAAA,CAAkC,CACxC,GAAI,CACF,IAAA,CAAK,IAAA,CAAOA,CAAAA,CAAO,CAAE,GAAGA,CAAK,CAAA,CAAI,KAAA,EACnC,OAASH,CAAAA,CAAK,CACZ,IAAA,CAAK,QAAA,CAAS,kBAAmBA,CAAG,EACtC,CACF,CAKA,MAAM,KAAA,EAAuB,CAC3B,GAAI,CACF,MAAM,IAAA,CAAK,SAAA,CAAU,KAAA,GACvB,OAASA,CAAAA,CAAK,CACZ,IAAA,CAAK,QAAA,CAAS,gBAAiBA,CAAG,EACpC,CACF,CAMQ,aAAaC,CAAAA,CAA0B,CAC7C,IAAMzG,CAAAA,CAAW,KAAK,MAAA,CAAO,YAAA,CAC7B,GAAI,CAACA,GAAYA,CAAAA,CAAS,MAAA,GAAW,CAAA,CAAG,OAAO,OAE/C,IAAA,IAAWnD,CAAAA,IAAWmD,CAAAA,CACpB,GAAI,OAAOnD,CAAAA,EAAY,QAAA,CAAA,CACrB,GAAI4J,CAAAA,CAAQ,SAAS5J,CAAO,CAAA,CAAG,OAAO,KAAA,CAAA,KAAA,GAC7BA,aAAmB,MAAA,EACxBA,CAAAA,CAAQ,IAAA,CAAK4J,CAAO,EAAG,OAAO,KAAA,CAItC,OAAO,MACT,CAEQ,QAAA,CAAA,GAAYG,CAAAA,CAAuB,CACzC,GAAI,KAAK,MAAA,CAAO,KAAA,CACd,GAAI,CACF,QAAQ,KAAA,CAAM,YAAA,CAAc,GAAGA,CAAI,EACrC,CAAA,KAAQ,CAER,CAEJ,CACF,EAcA,SAASP,EAAAA,CAAejJ,CAAAA,CAAiC,CACvD,GAAIA,CAAAA,YAAiB,KAAA,CACnB,OAAO,CACL,QAASA,CAAAA,CAAM,OAAA,EAAW,MAAA,CAAOA,CAAK,EACtC,IAAA,CAAMA,CAAAA,CAAM,WAAA,EAAa,IAAA,EAAQA,EAAM,IAAA,EAAQ,OAAA,CAC/C,KAAA,CAAOA,CAAAA,CAAM,MACb,GAAA,CAAKA,CACP,CAAA,CAGF,GAAI,OAAOA,CAAAA,EAAU,QAAA,CACnB,OAAO,CACL,QAASA,CAAAA,CACT,IAAA,CAAM,aAAA,CACN,KAAA,CAAO,IAAI,KAAA,CAAMA,CAAK,CAAA,CAAE,KAAA,CACxB,IAAKA,CACP,CAAA,CAGF,GAAIA,CAAAA,GAAU,MAAQ,OAAOA,CAAAA,EAAU,QAAA,CAAU,CAC/C,IAAMR,CAAAA,CAAMQ,CAAAA,CACZ,OAAO,CACL,QAAS,MAAA,CAAOR,CAAAA,CAAI,OAAA,EAAWA,CAAAA,CAAI,QAAU,IAAA,CAAK,SAAA,CAAUQ,CAAK,CAAC,EAClE,IAAA,CAAM,MAAA,CAAOR,CAAAA,CAAI,IAAA,EAAQA,EAAI,IAAA,EAAQ,aAAa,CAAA,CAClD,KAAA,CAAO,OAAOA,CAAAA,CAAI,KAAA,EAAU,QAAA,CAAWA,CAAAA,CAAI,MAAQ,MAAA,CACnD,GAAA,CAAKQ,CACP,CACF,CAEA,OAAO,CACL,OAAA,CAAS,MAAA,CAAOA,CAAK,CAAA,CACrB,IAAA,CAAM,cAAA,CACN,GAAA,CAAKA,CACP,CACF","file":"index.mjs","sourcesContent":["// ---------------------------------------------------------------------------\n// @uncaughtdev/core — breadcrumb ring-buffer store\n// ---------------------------------------------------------------------------\n\nimport type { Breadcrumb, BreadcrumbStore } from './types';\nimport { isoTimestamp } from './utils';\n\n/**\n * Create a fixed-capacity ring-buffer store for breadcrumbs.\n *\n * - O(1) `add`\n * - Oldest entries are silently overwritten when capacity is reached.\n * - Returned arrays are always copies — callers cannot mutate internal state.\n *\n * @param capacity Maximum breadcrumbs retained. Defaults to 20.\n */\nexport function createBreadcrumbStore(capacity: number = 20): BreadcrumbStore {\n const buffer: Array<Breadcrumb | undefined> = new Array(capacity);\n let head = 0; // next write index\n let size = 0; // current number of entries\n\n const store: BreadcrumbStore = {\n add(crumb: Omit<Breadcrumb, 'timestamp'>): void {\n const entry: Breadcrumb = {\n ...crumb,\n timestamp: isoTimestamp(),\n };\n\n buffer[head] = entry;\n head = (head + 1) % capacity;\n\n if (size < capacity) {\n size++;\n }\n },\n\n getAll(): Breadcrumb[] {\n if (size === 0) return [];\n\n const result: Breadcrumb[] = [];\n\n // The oldest entry sits at `(head - size + capacity) % capacity`\n const start = (head - size + capacity) % capacity;\n\n for (let i = 0; i < size; i++) {\n const idx = (start + i) % capacity;\n const entry = buffer[idx];\n if (entry) {\n // Return a shallow copy so callers cannot mutate internal data.\n result.push({ ...entry });\n }\n }\n\n return result;\n },\n\n getLast(n: number): Breadcrumb[] {\n if (n <= 0 || size === 0) return [];\n\n const count = Math.min(n, size);\n const result: Breadcrumb[] = [];\n\n // Walk backwards from the most recent entry.\n for (let i = 0; i < count; i++) {\n const idx = (head - 1 - i + capacity) % capacity;\n const entry = buffer[idx];\n if (entry) {\n result.unshift({ ...entry });\n }\n }\n\n return result;\n },\n\n clear(): void {\n buffer.fill(undefined);\n head = 0;\n size = 0;\n },\n };\n\n return store;\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — PII / secret sanitizer\n// ---------------------------------------------------------------------------\n\n/** Default key patterns that are always redacted. */\nconst DEFAULT_SENSITIVE_KEYS: string[] = [\n 'password',\n 'passwd',\n 'secret',\n 'token',\n 'apikey',\n 'api_key',\n 'authorization',\n 'credit_card',\n 'creditcard',\n 'card_number',\n 'cvv',\n 'ssn',\n 'social_security',\n 'private_key',\n 'access_token',\n 'refresh_token',\n 'session_id',\n 'cookie',\n];\n\n/** Headers that are always stripped regardless of key matching. */\nconst SENSITIVE_HEADERS = new Set(['authorization', 'cookie', 'set-cookie']);\n\nconst REDACTED = '[REDACTED]';\nconst MAX_STRING_LENGTH = 2048;\n\n/**\n * Build a single RegExp that matches any of the sensitive key patterns\n * (case-insensitive).\n */\nfunction buildKeyPattern(additionalKeys: string[] = []): RegExp {\n const all = [...DEFAULT_SENSITIVE_KEYS, ...additionalKeys];\n // Escape special regex characters in user-supplied keys\n const escaped = all.map((k) => k.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'));\n return new RegExp(escaped.join('|'), 'i');\n}\n\n/**\n * Deep-clone and sanitise `obj`, redacting values whose keys match\n * sensitive patterns.\n *\n * - Handles circular references (returns `\"[Circular]\"`).\n * - Truncates strings longer than 2 048 characters.\n * - Never mutates the original object.\n *\n * @param obj - The value to sanitise.\n * @param additionalKeys - Extra key patterns to redact on top of the defaults.\n */\nexport function sanitize<T>(obj: T, additionalKeys?: string[]): T {\n const pattern = buildKeyPattern(additionalKeys);\n const seen = new WeakSet();\n\n function walk(value: unknown, key?: string): unknown {\n // Redact if the current key is sensitive\n if (key && pattern.test(key)) {\n return REDACTED;\n }\n\n // Primitives\n if (value === null || value === undefined) return value;\n\n if (typeof value === 'string') {\n return value.length > MAX_STRING_LENGTH\n ? value.slice(0, MAX_STRING_LENGTH) + '...[truncated]'\n : value;\n }\n\n if (typeof value === 'number' || typeof value === 'boolean') {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return value.toString();\n }\n\n if (typeof value === 'function' || typeof value === 'symbol') {\n return undefined;\n }\n\n // Dates — return ISO string\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n // Arrays\n if (Array.isArray(value)) {\n if (seen.has(value)) return '[Circular]';\n seen.add(value);\n const result = value.map((item) => walk(item));\n seen.delete(value);\n return result;\n }\n\n // Plain objects\n if (typeof value === 'object') {\n if (seen.has(value as object)) return '[Circular]';\n seen.add(value as object);\n\n const result: Record<string, unknown> = {};\n\n for (const k of Object.keys(value as Record<string, unknown>)) {\n // Always strip sensitive headers\n if (SENSITIVE_HEADERS.has(k.toLowerCase())) {\n result[k] = REDACTED;\n continue;\n }\n\n result[k] = walk((value as Record<string, unknown>)[k], k);\n }\n\n seen.delete(value as object);\n return result;\n }\n\n return value;\n }\n\n return walk(obj) as T;\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — error fingerprinting\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a stable fingerprint for an error so that duplicate occurrences\n * of the same bug are grouped together.\n *\n * The fingerprint is an 8-character hex string derived from:\n * 1. The normalised error message (volatile parts stripped).\n * 2. The top 3 stack frames (file + function name, no line/col numbers).\n *\n * @param error - An object with at least `message` and optionally `stack` and `type`.\n */\nexport function generateFingerprint(error: {\n message?: string;\n type?: string;\n stack?: string;\n}): string {\n const normalisedMessage = normaliseMessage(error.message ?? '');\n const frames = extractTopFrames(error.stack ?? '', 3);\n const input = [error.type ?? 'Error', normalisedMessage, ...frames].join(\n '\\n'\n );\n return djb2(input);\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Strip volatile substrings from an error message so that trivially-different\n * occurrences of the same bug hash identically.\n */\nfunction normaliseMessage(msg: string): string {\n return (\n msg\n // UUIDs (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)\n .replace(\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,\n '<UUID>'\n )\n // Hex strings (8+ hex chars in a row)\n .replace(/\\b[0-9a-f]{8,}\\b/gi, '<HEX>')\n // Numbers longer than 3 digits\n .replace(/\\b\\d{4,}\\b/g, '<NUM>')\n // ISO timestamps\n .replace(\n /\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}[.\\d]*Z?/g,\n '<TIMESTAMP>'\n )\n // Hashed file paths — replace the hash portion (e.g. chunk-abc123.js → chunk-<HASH>.js)\n .replace(\n /([/\\\\])[a-zA-Z0-9_-]+[-.]([a-f0-9]{6,})\\.(js|ts|mjs|cjs|jsx|tsx)/g,\n '$1<FILE>.$3'\n )\n .trim()\n );\n}\n\n/**\n * Extract the top N stack frames as normalised \"file:function\" strings.\n * Line and column numbers are intentionally omitted so that minor code\n * changes do not alter the fingerprint.\n */\nfunction extractTopFrames(stack: string, count: number): string[] {\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: string[] = [];\n\n for (const line of lines) {\n if (frames.length >= count) break;\n\n const trimmed = line.trim();\n\n // V8 format: \" at FunctionName (file:line:col)\"\n // or \" at file:line:col\"\n const v8Match = trimmed.match(\n /at\\s+(?:(.+?)\\s+\\()?(?:(.+?):\\d+:\\d+)\\)?/\n );\n if (v8Match) {\n const fn = v8Match[1] || '<anonymous>';\n const file = normalisePath(v8Match[2] || '<unknown>');\n frames.push(`${file}:${fn}`);\n continue;\n }\n\n // SpiderMonkey / JavaScriptCore: \"functionName@file:line:col\"\n const smMatch = trimmed.match(/^(.+?)@(.+?):\\d+:\\d+/);\n if (smMatch) {\n const fn = smMatch[1] || '<anonymous>';\n const file = normalisePath(smMatch[2] || '<unknown>');\n frames.push(`${file}:${fn}`);\n continue;\n }\n }\n\n return frames;\n}\n\n/**\n * Normalise a file path by stripping query strings / hashes and collapsing\n * absolute filesystem prefixes.\n */\nfunction normalisePath(p: string): string {\n return p\n .replace(/[?#].*$/, '') // strip query / hash\n .replace(/^.*\\/node_modules\\//, 'node_modules/') // collapse deep paths\n .replace(/^(https?:\\/\\/[^/]+)/, '') // strip origin in URLs\n .replace(/^.*[/\\\\]/, ''); // keep only filename\n}\n\n/**\n * DJB2 hash → 8-character lowercase hex string.\n */\nfunction djb2(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n // hash * 33 + char\n hash = ((hash << 5) + hash + str.charCodeAt(i)) | 0;\n }\n // Convert to unsigned 32-bit then to 8-char hex\n return (hash >>> 0).toString(16).padStart(8, '0');\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — sliding-window rate limiter\n// ---------------------------------------------------------------------------\n\n/** Window duration in milliseconds (60 seconds). */\nconst WINDOW_MS = 60_000;\n\nexport interface RateLimiter {\n /**\n * Returns `true` if the event identified by `fingerprint` is allowed\n * through, `false` if it should be dropped.\n */\n shouldAllow(fingerprint: string): boolean;\n}\n\n/**\n * Create a rate limiter that enforces:\n * - A global maximum of `globalMax` events per 60-second window.\n * - A per-fingerprint maximum of `perFingerprintMax` events per 60-second window.\n *\n * Stale timestamps are lazily cleaned on every call to `shouldAllow`.\n *\n * @param globalMax Max events across all fingerprints. Defaults to 30.\n * @param perFingerprintMax Max events for a single fingerprint. Defaults to 5.\n */\nexport function createRateLimiter(\n globalMax: number = 30,\n perFingerprintMax: number = 5\n): RateLimiter {\n /** Per-fingerprint timestamp arrays. */\n const buckets = new Map<string, number[]>();\n /** Global timestamp array. */\n let globalTimestamps: number[] = [];\n\n /**\n * Remove timestamps older than the sliding window from an array (in-place)\n * and return the pruned array.\n */\n function prune(timestamps: number[], now: number): number[] {\n const cutoff = now - WINDOW_MS;\n // Find the first index that is within the window\n let start = 0;\n while (start < timestamps.length && timestamps[start] <= cutoff) {\n start++;\n }\n if (start > 0) {\n timestamps.splice(0, start);\n }\n return timestamps;\n }\n\n return {\n shouldAllow(fingerprint: string): boolean {\n const now = Date.now();\n\n // --- Global limit ---\n globalTimestamps = prune(globalTimestamps, now);\n if (globalTimestamps.length >= globalMax) {\n return false;\n }\n\n // --- Per-fingerprint limit ---\n let fpTimestamps = buckets.get(fingerprint);\n if (!fpTimestamps) {\n fpTimestamps = [];\n buckets.set(fingerprint, fpTimestamps);\n }\n prune(fpTimestamps, now);\n\n if (fpTimestamps.length >= perFingerprintMax) {\n return false;\n }\n\n // Record this event\n globalTimestamps.push(now);\n fpTimestamps.push(now);\n\n // Periodic cleanup: remove empty buckets to prevent unbounded memory growth\n if (buckets.size > 1000) {\n for (const [key, ts] of buckets) {\n if (ts.length === 0) {\n buckets.delete(key);\n }\n }\n }\n\n return true;\n },\n };\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — runtime / platform environment detector\n// ---------------------------------------------------------------------------\n\nimport type { EnvironmentInfo } from './types';\n\n/** Cached result so detection only runs once per process / page-load. */\nlet cached: EnvironmentInfo | undefined;\n\n/**\n * Detect the current runtime environment.\n *\n * - SSR-safe: every global access is guarded.\n * - Result is cached after the first invocation.\n */\nexport function detectEnvironment(): EnvironmentInfo {\n if (cached) return cached;\n\n const info: EnvironmentInfo = {};\n\n try {\n const isBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n const isNode =\n typeof process !== 'undefined' &&\n process.versions != null &&\n process.versions.node != null;\n\n // ----- Runtime ---------------------------------------------------------\n if (isNode) {\n info.runtime = 'node';\n info.runtimeVersion = process.versions.node;\n info.platform = process.platform;\n info.os = detectNodeOS();\n } else if (isBrowser) {\n info.runtime = 'browser';\n info.platform = 'web';\n\n const ua = navigator?.userAgent ?? '';\n const browserInfo = parseBrowserUA(ua);\n info.browser = browserInfo.name;\n info.browserVersion = browserInfo.version;\n info.os = parseOS(ua);\n info.deviceType = detectDeviceType();\n info.url = location?.href;\n info.locale = navigator?.language;\n info.timezone = Intl?.DateTimeFormat?.()?.resolvedOptions?.()?.timeZone;\n }\n\n // ----- Framework detection (works in both Node & browser) ---------------\n detectFramework(info);\n } catch {\n // Silent — environment detection must never throw.\n }\n\n cached = info;\n return info;\n}\n\n/**\n * Reset the cached environment (useful for testing).\n */\nexport function resetEnvironmentCache(): void {\n cached = undefined;\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\nfunction detectNodeOS(): string | undefined {\n try {\n const platform = process.platform;\n const map: Record<string, string> = {\n darwin: 'macOS',\n win32: 'Windows',\n linux: 'Linux',\n freebsd: 'FreeBSD',\n sunos: 'SunOS',\n };\n return map[platform] ?? platform;\n } catch {\n return undefined;\n }\n}\n\ninterface BrowserInfo {\n name?: string;\n version?: string;\n}\n\nfunction parseBrowserUA(ua: string): BrowserInfo {\n // Order matters — check more specific browsers first.\n const patterns: Array<{ name: string; regex: RegExp }> = [\n { name: 'Edge', regex: /Edg(?:e|A|iOS)?\\/(\\d+[\\d.]*)/ },\n { name: 'Opera', regex: /(?:OPR|Opera)\\/(\\d+[\\d.]*)/ },\n { name: 'Samsung Internet', regex: /SamsungBrowser\\/(\\d+[\\d.]*)/ },\n { name: 'UC Browser', regex: /UCBrowser\\/(\\d+[\\d.]*)/ },\n { name: 'Firefox', regex: /Firefox\\/(\\d+[\\d.]*)/ },\n { name: 'Chrome', regex: /Chrome\\/(\\d+[\\d.]*)/ },\n { name: 'Safari', regex: /Version\\/(\\d+[\\d.]*).*Safari/ },\n ];\n\n for (const { name, regex } of patterns) {\n const match = ua.match(regex);\n if (match) {\n return { name, version: match[1] };\n }\n }\n\n return {};\n}\n\nfunction parseOS(ua: string): string | undefined {\n if (/Windows/i.test(ua)) return 'Windows';\n if (/Mac OS X|macOS/i.test(ua)) return 'macOS';\n if (/Android/i.test(ua)) return 'Android';\n if (/iPhone|iPad|iPod/i.test(ua)) return 'iOS';\n if (/Linux/i.test(ua)) return 'Linux';\n if (/CrOS/i.test(ua)) return 'ChromeOS';\n return undefined;\n}\n\nfunction detectDeviceType(): string | undefined {\n try {\n if (typeof window === 'undefined') return undefined;\n\n const width = window.screen?.width ?? window.innerWidth;\n\n if (width <= 480) return 'mobile';\n if (width <= 1024) return 'tablet';\n return 'desktop';\n } catch {\n return undefined;\n }\n}\n\nfunction detectFramework(info: EnvironmentInfo): void {\n try {\n // ----- Browser-side markers -------------------------------------------\n if (typeof window !== 'undefined') {\n // Next.js injects __NEXT_DATA__\n if ((window as any).__NEXT_DATA__) {\n info.framework = 'next';\n info.frameworkVersion =\n (window as any).__NEXT_DATA__?.buildId ?? undefined;\n }\n // Remix injects __remixContext\n else if ((window as any).__remixContext) {\n info.framework = 'remix';\n }\n // Nuxt injects __NUXT__\n else if ((window as any).__NUXT__) {\n info.framework = 'nuxt';\n }\n }\n\n // ----- Node-side markers -----------------------------------------------\n if (\n typeof process !== 'undefined' &&\n process.env != null\n ) {\n // Framework env vars set during SSR / server build\n if (!info.framework) {\n if (process.env.__NEXT_PRIVATE_ORIGIN !== undefined || process.env.NEXT_RUNTIME) {\n info.framework = 'next';\n } else if (process.env.REMIX_DEV_ORIGIN !== undefined) {\n info.framework = 'remix';\n }\n }\n\n // Hosting platform markers\n if (process.env.VERCEL) {\n info.platform = info.platform ?? 'vercel';\n } else if (process.env.RAILWAY_PROJECT_ID) {\n info.platform = info.platform ?? 'railway';\n } else if (process.env.FLY_APP_NAME) {\n info.platform = info.platform ?? 'fly';\n } else if (process.env.AWS_LAMBDA_FUNCTION_NAME) {\n info.platform = info.platform ?? 'aws-lambda';\n } else if (process.env.GOOGLE_CLOUD_PROJECT) {\n info.platform = info.platform ?? 'gcp';\n }\n }\n\n // ----- Vite (import.meta.env) ------------------------------------------\n try {\n if (typeof (import.meta as any)?.env?.VITE_USER_NODE_ENV !== 'undefined') {\n if (!info.framework) {\n info.framework = 'vite';\n }\n }\n } catch {\n // import.meta may not exist in CJS contexts\n }\n } catch {\n // Silent — never throw during detection.\n }\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — fix-prompt builder\n// ---------------------------------------------------------------------------\n\nimport type { UncaughtEvent, Breadcrumb, EnvironmentInfo, OperationInfo, RequestInfo } from './types';\n\n/**\n * Build a structured Markdown prompt that can be pasted into an AI assistant\n * to diagnose and fix the production error described by `event`.\n *\n * Empty sections are omitted to keep the prompt concise.\n */\nexport function buildFixPrompt(event: Partial<UncaughtEvent>): string {\n const sections: string[] = [];\n\n // ----- Intro -------------------------------------------------------------\n sections.push(\n 'I have a production bug in my application that I need help diagnosing and fixing.\\n'\n );\n\n // ----- Error -------------------------------------------------------------\n if (event.error) {\n const location = extractLocation(event.error.stack);\n const lines: string[] = ['## Error', ''];\n lines.push(`- **Type:** ${event.error.type || 'Error'}`);\n lines.push(`- **Message:** ${event.error.message || '(no message)'}`);\n if (location) {\n lines.push(`- **Location:** ${location}`);\n }\n sections.push(lines.join('\\n'));\n }\n\n // ----- Stack Trace -------------------------------------------------------\n if (event.error?.stack) {\n const frames = event.error.stack\n .split('\\n')\n .slice(0, 15)\n .map((l) => l.trimEnd())\n .join('\\n');\n sections.push(`## Stack Trace\\n\\n\\`\\`\\`\\n${frames}\\n\\`\\`\\``);\n }\n\n // ----- Failed Operation --------------------------------------------------\n if (event.operation) {\n sections.push(formatOperation(event.operation));\n }\n\n // ----- HTTP Request Context ----------------------------------------------\n if (event.request) {\n sections.push(formatRequest(event.request));\n }\n\n // ----- User Session (last 5 breadcrumbs) ---------------------------------\n if (event.breadcrumbs && event.breadcrumbs.length > 0) {\n sections.push(formatBreadcrumbs(event.breadcrumbs));\n }\n\n // ----- Environment -------------------------------------------------------\n if (event.environment) {\n sections.push(formatEnvironment(event.environment));\n }\n\n // ----- React Component Stack ---------------------------------------------\n if (event.error?.componentStack) {\n sections.push(\n `## React Component Stack\\n\\n\\`\\`\\`\\n${event.error.componentStack.trim()}\\n\\`\\`\\``\n );\n }\n\n // ----- What I need -------------------------------------------------------\n sections.push(\n [\n '## What I need',\n '',\n '1. **Root cause analysis** — explain why this error is occurring.',\n '2. **A fix** — provide the corrected code with an explanation of the changes.',\n '3. **Prevention** — suggest any guards or tests to prevent this from happening again.',\n ].join('\\n')\n );\n\n return sections.join('\\n\\n') + '\\n';\n}\n\n// ---------------------------------------------------------------------------\n// Internal helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Extract the top-most location (file:line:col) from a stack trace string.\n */\nfunction extractLocation(stack?: string): string | undefined {\n if (!stack) return undefined;\n\n for (const line of stack.split('\\n')) {\n const trimmed = line.trim();\n\n // V8: \" at fn (file:line:col)\"\n const v8 = trimmed.match(/at\\s+(?:.+?\\s+\\()?(.+?:\\d+:\\d+)\\)?/);\n if (v8) return v8[1];\n\n // SpiderMonkey / JSC: \"fn@file:line:col\"\n const sm = trimmed.match(/@(.+?:\\d+:\\d+)/);\n if (sm) return sm[1];\n }\n\n return undefined;\n}\n\nfunction formatOperation(op: OperationInfo): string {\n const lines: string[] = ['## Failed Operation', ''];\n lines.push(`- **Provider:** ${op.provider}`);\n lines.push(`- **Type:** ${op.type}`);\n lines.push(`- **Method:** ${op.method}`);\n if (op.params) {\n lines.push(`- **Params:**`);\n lines.push('```json');\n lines.push(JSON.stringify(op.params, null, 2));\n lines.push('```');\n }\n if (op.errorCode) {\n lines.push(`- **Error Code:** ${op.errorCode}`);\n }\n if (op.errorDetails) {\n lines.push(`- **Error Details:** ${op.errorDetails}`);\n }\n return lines.join('\\n');\n}\n\nfunction formatRequest(req: RequestInfo): string {\n const lines: string[] = ['## HTTP Request Context', ''];\n if (req.method) lines.push(`- **Method:** ${req.method}`);\n if (req.url) lines.push(`- **URL:** ${req.url}`);\n if (req.body) {\n lines.push(`- **Body:**`);\n lines.push('```json');\n lines.push(\n typeof req.body === 'string'\n ? req.body\n : JSON.stringify(req.body, null, 2)\n );\n lines.push('```');\n }\n return lines.join('\\n');\n}\n\nfunction formatBreadcrumbs(crumbs: Breadcrumb[]): string {\n // Take the last 5 breadcrumbs\n const recent = crumbs.slice(-5);\n const lines: string[] = ['## User Session', ''];\n\n for (const crumb of recent) {\n const time = formatTime(crumb.timestamp);\n lines.push(`- \\`${time}\\` **[${crumb.type}]** ${crumb.message}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Extract HH:MM:SS from an ISO timestamp.\n */\nfunction formatTime(iso: string): string {\n try {\n const d = new Date(iso);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n } catch {\n return iso;\n }\n}\n\nfunction formatEnvironment(env: EnvironmentInfo): string {\n const lines: string[] = ['## Environment', ''];\n const entries: Array<[string, string | undefined]> = [\n ['Framework', env.framework],\n ['Framework Version', env.frameworkVersion],\n ['Runtime', env.runtime],\n ['Runtime Version', env.runtimeVersion],\n ['Platform', env.platform],\n ['Browser', env.browser ? `${env.browser} ${env.browserVersion ?? ''}`.trim() : undefined],\n ['OS', env.os],\n ['Device', env.deviceType],\n ['Locale', env.locale],\n ['Timezone', env.timezone],\n ['URL', env.url],\n ];\n\n for (const [label, value] of entries) {\n if (value) {\n lines.push(`- **${label}:** ${value}`);\n }\n }\n\n return lines.join('\\n');\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — transport layer (console / local-file / remote)\n// ---------------------------------------------------------------------------\n\nimport type {\n Transport,\n UncaughtConfig,\n UncaughtEvent,\n IssueEntry,\n} from './types';\nimport { safeStringify } from './utils';\n\n// ===================================================================\n// Factory\n// ===================================================================\n\n/**\n * Create the appropriate transport strategy based on config.\n */\nexport function createTransport(config: UncaughtConfig): Transport {\n const mode = config.transport ?? 'local';\n\n switch (mode) {\n case 'console':\n return createConsoleTransport(config);\n case 'remote':\n return createRemoteTransport(config);\n case 'local':\n default:\n return createLocalTransport(config);\n }\n}\n\n// ===================================================================\n// Console Transport\n// ===================================================================\n\nfunction createConsoleTransport(_config: UncaughtConfig): Transport {\n return {\n send(event: UncaughtEvent): void {\n try {\n const title = `[uncaught] ${event.error.type}: ${event.error.message}`;\n\n if (typeof console.group === 'function') {\n console.group(title);\n } else {\n console.log(`--- ${title} ---`);\n }\n\n console.error('Error:', event.error.message);\n if (event.error.stack) {\n console.log('Stack:', event.error.stack);\n }\n console.log('Event ID:', event.eventId);\n console.log('Fingerprint:', event.fingerprint);\n console.log('Breadcrumbs:', event.breadcrumbs);\n\n if (event.fixPrompt) {\n console.log('Fix Prompt:\\n', event.fixPrompt);\n }\n\n if (typeof console.groupEnd === 'function') {\n console.groupEnd();\n }\n } catch {\n // Never throw from transport.\n }\n },\n\n async flush(): Promise<void> {\n // Nothing to flush for console transport.\n },\n };\n}\n\n// ===================================================================\n// Local File Transport\n// ===================================================================\n\n/**\n * The local transport behaves differently depending on whether `fs` is\n * available (server / Node.js) or not (browser).\n *\n * **Server:** writes events directly to the `.uncaught/` directory.\n * **Browser:** POSTs to `/api/uncaught/local` and falls back to console.\n */\nfunction createLocalTransport(config: UncaughtConfig): Transport {\n // Detect server vs browser at transport creation time.\n const isServer = typeof process !== 'undefined' && process.versions?.node != null;\n\n if (isServer) {\n return createLocalFileTransport(config);\n }\n\n return createLocalClientTransport(config);\n}\n\n// ---------------------------------------------------------------------------\n// Local File Transport (Server / Node.js)\n// ---------------------------------------------------------------------------\n\ninterface FsModule {\n mkdir: (path: string, options: { recursive: boolean }) => Promise<void>;\n writeFile: (path: string, data: string, encoding: string) => Promise<void>;\n readFile: (path: string, encoding: string) => Promise<string>;\n rename: (from: string, to: string) => Promise<void>;\n access: (path: string) => Promise<void>;\n appendFile: (path: string, data: string) => Promise<void>;\n}\n\ninterface PathModule {\n join: (...parts: string[]) => string;\n resolve: (...parts: string[]) => string;\n}\n\nfunction createLocalFileTransport(config: UncaughtConfig): Transport {\n let fsPromises: FsModule | undefined;\n let pathModule: PathModule | undefined;\n let baseDir: string = '';\n let initialised = false;\n\n async function init(): Promise<void> {\n if (initialised) return;\n\n // Dynamic imports so this module can still be loaded in browsers without\n // causing a hard crash at parse time.\n const fs = await import('fs/promises');\n const path = await import('path');\n fsPromises = fs as unknown as FsModule;\n pathModule = path as unknown as PathModule;\n\n baseDir = config.localOutputDir ?? pathModule.resolve(process.cwd(), '.uncaught');\n\n // Ensure directory structure\n await fsPromises.mkdir(pathModule.join(baseDir, 'events'), { recursive: true });\n await fsPromises.mkdir(pathModule.join(baseDir, 'fix-prompts'), { recursive: true });\n\n // Auto-add .uncaught/ to .gitignore\n await ensureGitignore(fsPromises, pathModule);\n\n initialised = true;\n }\n\n async function ensureGitignore(fs: FsModule, path: PathModule): Promise<void> {\n try {\n const gitignorePath = path.resolve(process.cwd(), '.gitignore');\n let content = '';\n try {\n content = await fs.readFile(gitignorePath, 'utf-8');\n } catch {\n // File doesn't exist yet — that's fine.\n }\n\n if (!content.includes('.uncaught')) {\n const line = '\\n# Uncaught local error store\\n.uncaught/\\n';\n await fs.appendFile(gitignorePath, line);\n }\n } catch {\n // Non-critical — swallow.\n }\n }\n\n return {\n async send(event: UncaughtEvent): Promise<void> {\n try {\n await init();\n if (!fsPromises || !pathModule) return;\n\n const fp = event.fingerprint;\n const eventDir = pathModule.join(baseDir, 'events', fp);\n await fsPromises.mkdir(eventDir, { recursive: true });\n\n // --- Write timestamped event file (atomic: .tmp → rename) ----------\n const ts = event.timestamp.replace(/[:.]/g, '-');\n const eventFile = `event-${ts}.json`;\n const eventPath = pathModule.join(eventDir, eventFile);\n const tmpEventPath = eventPath + '.tmp';\n await fsPromises.writeFile(tmpEventPath, safeStringify(event), 'utf-8');\n await fsPromises.rename(tmpEventPath, eventPath);\n\n // --- Write / overwrite latest.json ---------------------------------\n const latestPath = pathModule.join(eventDir, 'latest.json');\n const tmpLatestPath = latestPath + '.tmp';\n await fsPromises.writeFile(tmpLatestPath, safeStringify(event), 'utf-8');\n await fsPromises.rename(tmpLatestPath, latestPath);\n\n // --- Write fix-prompt Markdown file --------------------------------\n const promptFile = `${fp}.md`;\n const promptPath = pathModule.join(baseDir, 'fix-prompts', promptFile);\n const tmpPromptPath = promptPath + '.tmp';\n await fsPromises.writeFile(tmpPromptPath, event.fixPrompt, 'utf-8');\n await fsPromises.rename(tmpPromptPath, promptPath);\n\n // --- Update issues.json index -------------------------------------\n await updateIssuesIndex(\n fsPromises,\n pathModule,\n baseDir,\n event,\n eventFile,\n promptFile\n );\n } catch {\n // Never crash the host app.\n }\n },\n\n async flush(): Promise<void> {\n // Local file transport writes synchronously per-event; nothing to flush.\n },\n };\n}\n\n/**\n * Read, update, and atomically write the `issues.json` index.\n */\nasync function updateIssuesIndex(\n fs: FsModule,\n path: PathModule,\n baseDir: string,\n event: UncaughtEvent,\n eventFile: string,\n promptFile: string\n): Promise<void> {\n const indexPath = path.join(baseDir, 'issues.json');\n\n let issues: IssueEntry[] = [];\n try {\n const raw = await fs.readFile(indexPath, 'utf-8');\n issues = JSON.parse(raw) as IssueEntry[];\n } catch {\n // File doesn't exist or is malformed — start fresh.\n }\n\n const existing = issues.find((i) => i.fingerprint === event.fingerprint);\n const userId = event.user?.id ?? event.user?.email ?? 'anonymous';\n\n if (existing) {\n existing.count += 1;\n existing.lastSeen = event.timestamp;\n existing.latestEventFile = eventFile;\n existing.fixPromptFile = promptFile;\n if (!existing.affectedUsers.includes(userId)) {\n existing.affectedUsers.push(userId);\n }\n // Re-open if previously resolved\n if (existing.status === 'resolved') {\n existing.status = 'open';\n }\n } else {\n issues.push({\n fingerprint: event.fingerprint,\n title: event.error.message,\n errorType: event.error.type,\n count: 1,\n affectedUsers: [userId],\n firstSeen: event.timestamp,\n lastSeen: event.timestamp,\n status: 'open',\n fixPromptFile: promptFile,\n latestEventFile: eventFile,\n });\n }\n\n const tmpIndexPath = indexPath + '.tmp';\n await fs.writeFile(tmpIndexPath, JSON.stringify(issues, null, 2), 'utf-8');\n await fs.rename(tmpIndexPath, indexPath);\n}\n\n// ---------------------------------------------------------------------------\n// Local Client Transport (Browser → POST /api/uncaught/local)\n// ---------------------------------------------------------------------------\n\nfunction createLocalClientTransport(_config: UncaughtConfig): Transport {\n const queue: UncaughtEvent[] = [];\n const consoleFallback = createConsoleTransport(_config);\n\n async function postEvents(events: UncaughtEvent[]): Promise<boolean> {\n try {\n const res = await fetch('/api/uncaught/local', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: safeStringify({ events }),\n });\n\n return res.ok || res.status === 202;\n } catch {\n return false;\n }\n }\n\n return {\n send(event: UncaughtEvent): void {\n queue.push(event);\n\n // Attempt to send immediately\n postEvents([event]).then((ok) => {\n if (!ok) {\n // Fallback to console\n consoleFallback.send(event);\n }\n }).catch(() => {\n consoleFallback.send(event);\n });\n },\n\n async flush(): Promise<void> {\n if (queue.length === 0) return;\n\n const batch = queue.splice(0, queue.length);\n const ok = await postEvents(batch);\n if (!ok) {\n // Fallback: log remaining to console\n for (const event of batch) {\n consoleFallback.send(event);\n }\n }\n },\n };\n}\n\n// ===================================================================\n// Remote Transport\n// ===================================================================\n\nfunction createRemoteTransport(config: UncaughtConfig): Transport {\n const endpoint = config.endpoint ?? '';\n const projectKey = config.projectKey ?? '';\n const maxRetries = 3;\n const batchSize = 10;\n const flushIntervalMs = 5_000;\n\n const queue: UncaughtEvent[] = [];\n let flushTimer: ReturnType<typeof setInterval> | undefined;\n let stopped = false;\n\n // Backoff delays in ms for retries (1s, 2s, 4s)\n const backoffDelays = [1000, 2000, 4000];\n\n async function sendBatch(events: UncaughtEvent[]): Promise<void> {\n if (events.length === 0 || stopped) return;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const res = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...(projectKey ? { 'X-Project-Key': projectKey } : {}),\n },\n body: safeStringify({ events }),\n });\n\n if (res.ok || res.status === 202) {\n return; // Success\n }\n\n if (res.status === 401) {\n // Unauthorized — stop sending entirely.\n stopped = true;\n if (flushTimer) clearInterval(flushTimer);\n return;\n }\n\n if (res.status === 429) {\n // Rate limited — use longer backoff\n const retryAfter = parseInt(\n res.headers?.get?.('Retry-After') ?? '10',\n 10\n );\n await sleep(retryAfter * 1000);\n continue;\n }\n\n // Other server errors — retry with backoff\n if (attempt < maxRetries) {\n await sleep(backoffDelays[attempt] ?? 4000);\n }\n } catch {\n // Network error — retry\n if (attempt < maxRetries) {\n await sleep(backoffDelays[attempt] ?? 4000);\n }\n }\n }\n // All retries exhausted — events are dropped silently.\n }\n\n function startFlushing(): void {\n if (flushTimer) return;\n flushTimer = setInterval(() => {\n if (queue.length > 0) {\n const batch = queue.splice(0, batchSize);\n sendBatch(batch).catch(() => {\n // Swallow — never crash.\n });\n }\n }, flushIntervalMs);\n\n // Ensure the timer does not prevent Node.js from exiting.\n if (typeof flushTimer === 'object' && 'unref' in flushTimer) {\n (flushTimer as { unref: () => void }).unref();\n }\n }\n\n // Register sendBeacon on page unload (browser only)\n function registerBeacon(): void {\n try {\n if (\n typeof window !== 'undefined' &&\n typeof navigator?.sendBeacon === 'function'\n ) {\n window.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden' && queue.length > 0) {\n const payload = safeStringify({ events: queue.splice(0, queue.length) });\n navigator.sendBeacon(endpoint, payload);\n }\n });\n\n window.addEventListener('pagehide', () => {\n if (queue.length > 0) {\n const payload = safeStringify({ events: queue.splice(0, queue.length) });\n navigator.sendBeacon(endpoint, payload);\n }\n });\n }\n } catch {\n // Not in a browser — that's fine.\n }\n }\n\n startFlushing();\n registerBeacon();\n\n return {\n send(event: UncaughtEvent): void {\n if (stopped) return;\n\n queue.push(event);\n\n // Flush immediately if batch size reached\n if (queue.length >= batchSize) {\n const batch = queue.splice(0, batchSize);\n sendBatch(batch).catch(() => {\n // Swallow.\n });\n }\n },\n\n async flush(): Promise<void> {\n if (flushTimer) {\n clearInterval(flushTimer);\n flushTimer = undefined;\n }\n\n while (queue.length > 0) {\n const batch = queue.splice(0, batchSize);\n await sendBatch(batch);\n }\n },\n };\n}\n\n// ===================================================================\n// Helpers\n// ===================================================================\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","// ---------------------------------------------------------------------------\n// @uncaughtdev/core — UncaughtClient (SDK entry-point)\n// ---------------------------------------------------------------------------\n\nimport type {\n UncaughtConfig,\n UncaughtEvent,\n Breadcrumb,\n BreadcrumbStore,\n Transport,\n SeverityLevel,\n UserInfo,\n RequestInfo,\n OperationInfo,\n} from './types';\n\nimport { generateUUID, isoTimestamp } from './utils';\nimport { createBreadcrumbStore } from './breadcrumbs';\nimport { sanitize } from './sanitizer';\nimport { generateFingerprint } from './fingerprint';\nimport { createRateLimiter, type RateLimiter } from './rate-limiter';\nimport { detectEnvironment } from './env-detector';\nimport { buildFixPrompt } from './prompt-builder';\nimport { createTransport } from './transport';\n\nconst SDK_NAME = '@uncaughtdev/core';\nconst SDK_VERSION = '0.1.0';\n\n// ---------------------------------------------------------------------------\n// Module-level singleton\n// ---------------------------------------------------------------------------\n\nlet _client: UncaughtClient | undefined;\n\n/**\n * Initialise the Uncaught SDK. Calling this more than once replaces the\n * previous client instance.\n */\nexport function initUncaught(config: UncaughtConfig): UncaughtClient {\n _client = new UncaughtClient(config);\n return _client;\n}\n\n/**\n * Return the current singleton client, or `undefined` if `initUncaught` has\n * not been called.\n */\nexport function getClient(): UncaughtClient | undefined {\n return _client;\n}\n\n// ---------------------------------------------------------------------------\n// Client class\n// ---------------------------------------------------------------------------\n\nexport class UncaughtClient {\n private readonly config: Required<\n Pick<UncaughtConfig, 'enabled' | 'debug' | 'maxBreadcrumbs' | 'maxEventsPerMinute'>\n > &\n UncaughtConfig;\n\n private readonly breadcrumbs: BreadcrumbStore;\n private readonly transport: Transport;\n private readonly rateLimiter: RateLimiter;\n private readonly sessionId: string;\n private user: UserInfo | undefined;\n\n constructor(config: UncaughtConfig) {\n this.config = {\n enabled: true,\n debug: false,\n maxBreadcrumbs: 20,\n maxEventsPerMinute: 30,\n ...config,\n };\n\n this.breadcrumbs = createBreadcrumbStore(this.config.maxBreadcrumbs);\n this.transport = createTransport(this.config);\n this.rateLimiter = createRateLimiter(this.config.maxEventsPerMinute);\n this.sessionId = generateUUID();\n }\n\n // -----------------------------------------------------------------------\n // Public API\n // -----------------------------------------------------------------------\n\n /**\n * Capture an error and send it through the transport pipeline.\n *\n * @returns The event ID, or `undefined` if the event was dropped.\n */\n captureError(\n error: unknown,\n context?: {\n request?: RequestInfo;\n operation?: OperationInfo;\n componentStack?: string;\n level?: SeverityLevel;\n }\n ): string | undefined {\n try {\n if (!this.config.enabled) return undefined;\n\n // --- Normalise error -------------------------------------------------\n const errorInfo = normaliseError(error);\n\n if (context?.componentStack) {\n errorInfo.componentStack = context.componentStack;\n }\n\n // --- Check ignoreErrors ----------------------------------------------\n if (this.shouldIgnore(errorInfo.message)) {\n this.debugLog('Event ignored by ignoreErrors filter');\n return undefined;\n }\n\n // --- Fingerprint -----------------------------------------------------\n const fingerprint = generateFingerprint(errorInfo);\n\n // --- Rate limit ------------------------------------------------------\n if (!this.rateLimiter.shouldAllow(fingerprint)) {\n this.debugLog(`Rate-limited: ${fingerprint}`);\n return undefined;\n }\n\n // --- Collect breadcrumbs ---------------------------------------------\n const crumbs = this.breadcrumbs.getAll();\n\n // --- Detect environment ----------------------------------------------\n const environment = detectEnvironment();\n\n // --- Build event -----------------------------------------------------\n const eventId = generateUUID();\n let event: UncaughtEvent = {\n eventId,\n timestamp: isoTimestamp(),\n projectKey: this.config.projectKey,\n level: context?.level ?? 'error',\n fingerprint,\n error: errorInfo,\n breadcrumbs: crumbs,\n request: context?.request,\n operation: context?.operation,\n environment,\n user: this.user\n ? { ...this.user, sessionId: this.sessionId }\n : { sessionId: this.sessionId },\n fixPrompt: '', // will be set below\n sdk: { name: SDK_NAME, version: SDK_VERSION },\n };\n\n // --- Sanitise --------------------------------------------------------\n event = sanitize(event, this.config.sanitizeKeys) as UncaughtEvent;\n\n // --- Build fix prompt ------------------------------------------------\n event.fixPrompt = buildFixPrompt(event);\n\n // --- beforeSend hook -------------------------------------------------\n if (this.config.beforeSend) {\n const result = this.config.beforeSend(event);\n if (result === null) {\n this.debugLog('Event dropped by beforeSend');\n return undefined;\n }\n event = result;\n }\n\n // --- Send ------------------------------------------------------------\n this.transport.send(event);\n this.debugLog(`Captured event: ${eventId} (${fingerprint})`);\n return eventId;\n } catch (err) {\n this.debugLog('captureError failed:', err);\n return undefined;\n }\n }\n\n /**\n * Capture a plain message (not backed by an Error instance).\n */\n captureMessage(\n message: string,\n level: SeverityLevel = 'info'\n ): string | undefined {\n try {\n return this.captureError(new Error(message), { level });\n } catch (err) {\n this.debugLog('captureMessage failed:', err);\n return undefined;\n }\n }\n\n /**\n * Add a breadcrumb to the ring buffer.\n */\n addBreadcrumb(crumb: Omit<Breadcrumb, 'timestamp'>): void {\n try {\n if (!this.config.enabled) return;\n this.breadcrumbs.add(crumb);\n } catch (err) {\n this.debugLog('addBreadcrumb failed:', err);\n }\n }\n\n /**\n * Set user context that will be attached to subsequent events.\n */\n setUser(user: UserInfo | undefined): void {\n try {\n this.user = user ? { ...user } : undefined;\n } catch (err) {\n this.debugLog('setUser failed:', err);\n }\n }\n\n /**\n * Flush all queued events to the transport.\n */\n async flush(): Promise<void> {\n try {\n await this.transport.flush();\n } catch (err) {\n this.debugLog('flush failed:', err);\n }\n }\n\n // -----------------------------------------------------------------------\n // Internal helpers\n // -----------------------------------------------------------------------\n\n private shouldIgnore(message: string): boolean {\n const patterns = this.config.ignoreErrors;\n if (!patterns || patterns.length === 0) return false;\n\n for (const pattern of patterns) {\n if (typeof pattern === 'string') {\n if (message.includes(pattern)) return true;\n } else if (pattern instanceof RegExp) {\n if (pattern.test(message)) return true;\n }\n }\n\n return false;\n }\n\n private debugLog(...args: unknown[]): void {\n if (this.config.debug) {\n try {\n console.debug('[uncaught]', ...args);\n } catch {\n // Even console.debug can theoretically throw in exotic environments.\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Error normalisation\n// ---------------------------------------------------------------------------\n\ninterface NormalisedError {\n message: string;\n type: string;\n stack?: string;\n componentStack?: string;\n raw?: unknown;\n}\n\nfunction normaliseError(error: unknown): NormalisedError {\n if (error instanceof Error) {\n return {\n message: error.message || String(error),\n type: error.constructor?.name || error.name || 'Error',\n stack: error.stack,\n raw: error,\n };\n }\n\n if (typeof error === 'string') {\n return {\n message: error,\n type: 'StringError',\n stack: new Error(error).stack,\n raw: error,\n };\n }\n\n if (error !== null && typeof error === 'object') {\n const obj = error as Record<string, unknown>;\n return {\n message: String(obj.message ?? obj.reason ?? JSON.stringify(error)),\n type: String(obj.name ?? obj.type ?? 'ObjectError'),\n stack: typeof obj.stack === 'string' ? obj.stack : undefined,\n raw: error,\n };\n }\n\n return {\n message: String(error),\n type: 'UnknownError',\n raw: error,\n };\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal type for the Next.js Pages API request.
|
|
3
|
+
* We intentionally avoid importing `next` so that `@uncaughtdev/core` has
|
|
4
|
+
* zero runtime dependencies.
|
|
5
|
+
*/
|
|
6
|
+
interface PagesApiRequest {
|
|
7
|
+
method?: string;
|
|
8
|
+
body?: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Minimal type for the Next.js Pages API response.
|
|
12
|
+
*/
|
|
13
|
+
interface PagesApiResponse {
|
|
14
|
+
status: (code: number) => PagesApiResponse;
|
|
15
|
+
json: (body: unknown) => void;
|
|
16
|
+
setHeader?: (name: string, value: string) => PagesApiResponse;
|
|
17
|
+
end?: () => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Next.js Pages Router API handler (`/pages/api/uncaught/local.ts`).
|
|
21
|
+
*
|
|
22
|
+
* Accepts POST requests with `{ events: UncaughtEvent[] }` and writes them
|
|
23
|
+
* to `.uncaught/`.
|
|
24
|
+
*
|
|
25
|
+
* Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.
|
|
26
|
+
*/
|
|
27
|
+
declare function handler(req: PagesApiRequest, res: PagesApiResponse): Promise<void>;
|
|
28
|
+
|
|
29
|
+
export { handler as default };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal type for the Next.js Pages API request.
|
|
3
|
+
* We intentionally avoid importing `next` so that `@uncaughtdev/core` has
|
|
4
|
+
* zero runtime dependencies.
|
|
5
|
+
*/
|
|
6
|
+
interface PagesApiRequest {
|
|
7
|
+
method?: string;
|
|
8
|
+
body?: unknown;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Minimal type for the Next.js Pages API response.
|
|
12
|
+
*/
|
|
13
|
+
interface PagesApiResponse {
|
|
14
|
+
status: (code: number) => PagesApiResponse;
|
|
15
|
+
json: (body: unknown) => void;
|
|
16
|
+
setHeader?: (name: string, value: string) => PagesApiResponse;
|
|
17
|
+
end?: () => void;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Next.js Pages Router API handler (`/pages/api/uncaught/local.ts`).
|
|
21
|
+
*
|
|
22
|
+
* Accepts POST requests with `{ events: UncaughtEvent[] }` and writes them
|
|
23
|
+
* to `.uncaught/`.
|
|
24
|
+
*
|
|
25
|
+
* Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.
|
|
26
|
+
*/
|
|
27
|
+
declare function handler(req: PagesApiRequest, res: PagesApiResponse): Promise<void>;
|
|
28
|
+
|
|
29
|
+
export { handler as default };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkFFHQ452Q_js=require('./chunk-FFHQ452Q.js');require('./chunk-E76GW6KF.js');async function r(s,t){try{if(s.method!=="POST"){t.status(405).json({error:"Method not allowed"});return}if(typeof process<"u"&&process.env.NODE_ENV==="production"&&process.env.UNCAUGHT_LOCAL_IN_PROD!=="true"){t.status(403).json({error:"Local handler is disabled in production"});return}let e=s.body;if(!e||typeof e!="object"||!Array.isArray(e.events)){t.status(400).json({error:'Payload must contain an "events" array'});return}let n=e.events;if(n.length===0){t.status(202).json({accepted:0});return}await chunkFFHQ452Q_js.b(n),t.status(202).json({accepted:n.length});}catch(e){let n=e instanceof Error?e.message:"Internal server error";t.status(500).json({error:n});}}module.exports=r;//# sourceMappingURL=local-api-handler-pages.js.map
|
|
2
|
+
//# sourceMappingURL=local-api-handler-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local-api-handler-pages.ts"],"names":["handler","req","res","body","events","writeEvents","err","message"],"mappings":"gGAyCA,eAAOA,CAAAA,CACLC,CAAAA,CACAC,CAAAA,CACe,CACf,GAAI,CAEF,GAAID,CAAAA,CAAI,MAAA,GAAW,MAAA,CAAQ,CACzBC,CAAAA,CAAI,OAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,oBAAqB,CAAC,CAAA,CACpD,MACF,CAGA,GACE,OAAO,OAAA,CAAY,GAAA,EACnB,OAAA,CAAQ,GAAA,CAAI,WAAa,YAAA,EACzB,OAAA,CAAQ,GAAA,CAAI,sBAAA,GAA2B,MAAA,CACvC,CACAA,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,yCAA0C,CAAC,CAAA,CACzE,MACF,CAGA,IAAMC,CAAAA,CAAOF,CAAAA,CAAI,IAAA,CAEjB,GACE,CAACE,CAAAA,EACD,OAAOA,CAAAA,EAAS,QAAA,EAChB,CAAC,KAAA,CAAM,OAAA,CAASA,CAAAA,CAAiC,MAAM,EACvD,CACAD,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,wCAAyC,CAAC,CAAA,CACxE,MACF,CAEA,IAAME,CAAAA,CAAUD,CAAAA,CAAqC,OAErD,GAAIC,CAAAA,CAAO,MAAA,GAAW,CAAA,CAAG,CACvBF,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,QAAA,CAAU,CAAE,CAAC,CAAA,CACpC,MACF,CAGA,MAAMG,kBAAAA,CAAYD,CAAM,CAAA,CAExBF,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,QAAA,CAAUE,CAAAA,CAAO,MAAO,CAAC,EAClD,CAAA,MAASE,EAAK,CACZ,IAAMC,CAAAA,CACJD,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,uBAAA,CACvCJ,EAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAOK,CAAQ,CAAC,EACzC,CACF","file":"local-api-handler-pages.js","sourcesContent":["// ---------------------------------------------------------------------------\n// @uncaughtdev/core — Next.js Pages Router local API handler\n// ---------------------------------------------------------------------------\n//\n// Usage:\n// // pages/api/uncaught/local.ts\n// export { default } from '@uncaughtdev/core/local-api-handler/pages';\n//\n// ---------------------------------------------------------------------------\n\nimport type { UncaughtEvent } from './types';\nimport { writeEvents } from './local-api-handler';\n\n/**\n * Minimal type for the Next.js Pages API request.\n * We intentionally avoid importing `next` so that `@uncaughtdev/core` has\n * zero runtime dependencies.\n */\ninterface PagesApiRequest {\n method?: string;\n body?: unknown;\n}\n\n/**\n * Minimal type for the Next.js Pages API response.\n */\ninterface PagesApiResponse {\n status: (code: number) => PagesApiResponse;\n json: (body: unknown) => void;\n setHeader?: (name: string, value: string) => PagesApiResponse;\n end?: () => void;\n}\n\n/**\n * Next.js Pages Router API handler (`/pages/api/uncaught/local.ts`).\n *\n * Accepts POST requests with `{ events: UncaughtEvent[] }` and writes them\n * to `.uncaught/`.\n *\n * Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.\n */\nexport default async function handler(\n req: PagesApiRequest,\n res: PagesApiResponse\n): Promise<void> {\n try {\n // --- Method check ------------------------------------------------------\n if (req.method !== 'POST') {\n res.status(405).json({ error: 'Method not allowed' });\n return;\n }\n\n // --- Production guard --------------------------------------------------\n if (\n typeof process !== 'undefined' &&\n process.env.NODE_ENV === 'production' &&\n process.env.UNCAUGHT_LOCAL_IN_PROD !== 'true'\n ) {\n res.status(403).json({ error: 'Local handler is disabled in production' });\n return;\n }\n\n // --- Validate body -----------------------------------------------------\n const body = req.body;\n\n if (\n !body ||\n typeof body !== 'object' ||\n !Array.isArray((body as Record<string, unknown>).events)\n ) {\n res.status(400).json({ error: 'Payload must contain an \"events\" array' });\n return;\n }\n\n const events = (body as { events: UncaughtEvent[] }).events;\n\n if (events.length === 0) {\n res.status(202).json({ accepted: 0 });\n return;\n }\n\n // --- Write events to disk ----------------------------------------------\n await writeEvents(events);\n\n res.status(202).json({ accepted: events.length });\n } catch (err) {\n const message =\n err instanceof Error ? err.message : 'Internal server error';\n res.status(500).json({ error: message });\n }\n}\n"]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {b}from'./chunk-JALIO2BZ.mjs';import'./chunk-P6JRN5CN.mjs';async function r(s,t){try{if(s.method!=="POST"){t.status(405).json({error:"Method not allowed"});return}if(typeof process<"u"&&process.env.NODE_ENV==="production"&&process.env.UNCAUGHT_LOCAL_IN_PROD!=="true"){t.status(403).json({error:"Local handler is disabled in production"});return}let e=s.body;if(!e||typeof e!="object"||!Array.isArray(e.events)){t.status(400).json({error:'Payload must contain an "events" array'});return}let n=e.events;if(n.length===0){t.status(202).json({accepted:0});return}await b(n),t.status(202).json({accepted:n.length});}catch(e){let n=e instanceof Error?e.message:"Internal server error";t.status(500).json({error:n});}}export{r as default};//# sourceMappingURL=local-api-handler-pages.mjs.map
|
|
2
|
+
//# sourceMappingURL=local-api-handler-pages.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local-api-handler-pages.ts"],"names":["handler","req","res","body","events","writeEvents","err","message"],"mappings":"kEAyCA,eAAOA,CAAAA,CACLC,CAAAA,CACAC,CAAAA,CACe,CACf,GAAI,CAEF,GAAID,CAAAA,CAAI,MAAA,GAAW,MAAA,CAAQ,CACzBC,CAAAA,CAAI,OAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,oBAAqB,CAAC,CAAA,CACpD,MACF,CAGA,GACE,OAAO,OAAA,CAAY,GAAA,EACnB,OAAA,CAAQ,GAAA,CAAI,WAAa,YAAA,EACzB,OAAA,CAAQ,GAAA,CAAI,sBAAA,GAA2B,MAAA,CACvC,CACAA,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,yCAA0C,CAAC,CAAA,CACzE,MACF,CAGA,IAAMC,CAAAA,CAAOF,CAAAA,CAAI,IAAA,CAEjB,GACE,CAACE,CAAAA,EACD,OAAOA,CAAAA,EAAS,QAAA,EAChB,CAAC,KAAA,CAAM,OAAA,CAASA,CAAAA,CAAiC,MAAM,EACvD,CACAD,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAO,wCAAyC,CAAC,CAAA,CACxE,MACF,CAEA,IAAME,CAAAA,CAAUD,CAAAA,CAAqC,OAErD,GAAIC,CAAAA,CAAO,MAAA,GAAW,CAAA,CAAG,CACvBF,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,QAAA,CAAU,CAAE,CAAC,CAAA,CACpC,MACF,CAGA,MAAMG,CAAAA,CAAYD,CAAM,CAAA,CAExBF,CAAAA,CAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,QAAA,CAAUE,CAAAA,CAAO,MAAO,CAAC,EAClD,CAAA,MAASE,EAAK,CACZ,IAAMC,CAAAA,CACJD,CAAAA,YAAe,KAAA,CAAQA,CAAAA,CAAI,OAAA,CAAU,uBAAA,CACvCJ,EAAI,MAAA,CAAO,GAAG,CAAA,CAAE,IAAA,CAAK,CAAE,KAAA,CAAOK,CAAQ,CAAC,EACzC,CACF","file":"local-api-handler-pages.mjs","sourcesContent":["// ---------------------------------------------------------------------------\n// @uncaughtdev/core — Next.js Pages Router local API handler\n// ---------------------------------------------------------------------------\n//\n// Usage:\n// // pages/api/uncaught/local.ts\n// export { default } from '@uncaughtdev/core/local-api-handler/pages';\n//\n// ---------------------------------------------------------------------------\n\nimport type { UncaughtEvent } from './types';\nimport { writeEvents } from './local-api-handler';\n\n/**\n * Minimal type for the Next.js Pages API request.\n * We intentionally avoid importing `next` so that `@uncaughtdev/core` has\n * zero runtime dependencies.\n */\ninterface PagesApiRequest {\n method?: string;\n body?: unknown;\n}\n\n/**\n * Minimal type for the Next.js Pages API response.\n */\ninterface PagesApiResponse {\n status: (code: number) => PagesApiResponse;\n json: (body: unknown) => void;\n setHeader?: (name: string, value: string) => PagesApiResponse;\n end?: () => void;\n}\n\n/**\n * Next.js Pages Router API handler (`/pages/api/uncaught/local.ts`).\n *\n * Accepts POST requests with `{ events: UncaughtEvent[] }` and writes them\n * to `.uncaught/`.\n *\n * Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.\n */\nexport default async function handler(\n req: PagesApiRequest,\n res: PagesApiResponse\n): Promise<void> {\n try {\n // --- Method check ------------------------------------------------------\n if (req.method !== 'POST') {\n res.status(405).json({ error: 'Method not allowed' });\n return;\n }\n\n // --- Production guard --------------------------------------------------\n if (\n typeof process !== 'undefined' &&\n process.env.NODE_ENV === 'production' &&\n process.env.UNCAUGHT_LOCAL_IN_PROD !== 'true'\n ) {\n res.status(403).json({ error: 'Local handler is disabled in production' });\n return;\n }\n\n // --- Validate body -----------------------------------------------------\n const body = req.body;\n\n if (\n !body ||\n typeof body !== 'object' ||\n !Array.isArray((body as Record<string, unknown>).events)\n ) {\n res.status(400).json({ error: 'Payload must contain an \"events\" array' });\n return;\n }\n\n const events = (body as { events: UncaughtEvent[] }).events;\n\n if (events.length === 0) {\n res.status(202).json({ accepted: 0 });\n return;\n }\n\n // --- Write events to disk ----------------------------------------------\n await writeEvents(events);\n\n res.status(202).json({ accepted: events.length });\n } catch (err) {\n const message =\n err instanceof Error ? err.message : 'Internal server error';\n res.status(500).json({ error: message });\n }\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { U as UncaughtEvent } from './types-CjgYXVc_.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Next.js App Router POST handler.
|
|
5
|
+
* Accepts `{ events: UncaughtEvent[] }` and writes them to `.uncaught/`.
|
|
6
|
+
*
|
|
7
|
+
* Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.
|
|
8
|
+
*/
|
|
9
|
+
declare function POST(request: Request): Promise<Response>;
|
|
10
|
+
declare function writeEvents(events: UncaughtEvent[]): Promise<void>;
|
|
11
|
+
|
|
12
|
+
export { POST, writeEvents };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { U as UncaughtEvent } from './types-CjgYXVc_.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Next.js App Router POST handler.
|
|
5
|
+
* Accepts `{ events: UncaughtEvent[] }` and writes them to `.uncaught/`.
|
|
6
|
+
*
|
|
7
|
+
* Blocked in production unless `UNCAUGHT_LOCAL_IN_PROD=true` is set.
|
|
8
|
+
*/
|
|
9
|
+
declare function POST(request: Request): Promise<Response>;
|
|
10
|
+
declare function writeEvents(events: UncaughtEvent[]): Promise<void>;
|
|
11
|
+
|
|
12
|
+
export { POST, writeEvents };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkFFHQ452Q_js=require('./chunk-FFHQ452Q.js');require('./chunk-E76GW6KF.js');Object.defineProperty(exports,"POST",{enumerable:true,get:function(){return chunkFFHQ452Q_js.a}});Object.defineProperty(exports,"writeEvents",{enumerable:true,get:function(){return chunkFFHQ452Q_js.b}});//# sourceMappingURL=local-api-handler.js.map
|
|
2
|
+
//# sourceMappingURL=local-api-handler.js.map
|