browser-error-log 0.0.0-stage → 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hyeonse Im
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,96 @@
1
- # Temporary Holding Version
1
+ # browser-error-log
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ A small browser error SDK for a collector you control. Use your own backend or the repository's self-hosted Node.js collector, which stores events in SQLite or rotating JSONL files.
4
+
5
+ ## Why use it?
6
+
7
+ - **Choose where events go.** There is no built-in hosted endpoint or separate analytics destination. Configure `endpoint` or supply your own `transport`.
8
+ - **Keep the browser dependency small.** No runtime framework dependency; ESM, CommonJS, and TypeScript declarations are provided. The repository enforces a 20 KiB gzip budget for the browser SDK, excluding the viewer and optional React adapter.
9
+ - **Control events before delivery.** Filter or edit them with `beforeSend`, remove path identifiers with `sanitizeUrl`, and choose which HTTP responses matter with `shouldCaptureHttp`.
10
+ - **Start with useful error context.** Collect JavaScript exceptions, unhandled promises, fetch/XHR failures, and manually reported errors, with project, release, page, and occurrence time. Console capture is opt-in.
11
+ - **Keep storage portable.** The companion collector offers SQLite with a live viewer, or JSONL logs that can be exported and inspected locally. You can implement the same versioned contract in your own backend.
12
+
13
+ ## Install
14
+
15
+ ```sh
16
+ npm install browser-error-log
17
+ ```
18
+
19
+ The `browser-error-log-protocol` dependency resolves from npm. For a local source checkout before publication, use Node.js 24, `npm ci`, and `npm run check:package`, then install the protocol and browser tarballs together as shown in the [SDK guide](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/personal-sdk.md).
20
+
21
+ ## Connect in three steps
22
+
23
+ 1. In the source checkout, start your collector. Set the exact origin of the app that will send events:
24
+
25
+ ```sh
26
+ MICRO_PROJECTS=my-web MICRO_ALLOWED_ORIGINS=http://localhost:5173 npm run micro
27
+ ```
28
+
29
+ 2. In your app's browser entry point, initialize once:
30
+
31
+ ```ts
32
+ import { init } from 'browser-error-log';
33
+
34
+ export const errorLog = init({
35
+ project: 'my-web',
36
+ endpoint: 'http://127.0.0.1:4319/api/events',
37
+ environment: 'development',
38
+ release: 'my-release',
39
+ });
40
+ ```
41
+
42
+ 3. Send a diagnostic error, then open `http://127.0.0.1:4319/`:
43
+
44
+ ```ts
45
+ errorLog.captureException(new Error('Connection check'));
46
+ await errorLog.flush();
47
+ console.log(errorLog.getStats()); // sent: 1 when delivery succeeds
48
+ ```
49
+
50
+ Keep the client alive for the app's lifetime. Use `destroy()` for test cleanup or when disposing the app; it removes instrumentation and discards pending events. `flush()` completes the SDK's delivery attempts, not a guarantee of storage: check `getStats()` and the collector. Capturing starts only after initialization.
51
+
52
+ Use the [self-hosting guide](https://github.com/hyeonse-swing/browser-error-log/blob/main/docs/micro-server.md) for external hosting. Production apps need their own HTTPS collector, exact allowed origins, persistent storage, and viewer authentication. `localhost` and `127.0.0.1` are different origins. The viewer password belongs only on the server; do not put it in SDK configuration.
53
+
54
+ ## Capture handled errors
55
+
56
+ ```ts
57
+ try {
58
+ await loadDashboard();
59
+ } catch (error) {
60
+ errorLog.captureException(error, { context: { action: 'load-dashboard' } });
61
+ }
62
+ ```
63
+
64
+ The optional `browser-error-log-react` package provides an Error Boundary. The base SDK does not require React. Imports and initialization are safe during SSR but do not collect server-side errors; initialize in your framework's browser/client entry point.
65
+
66
+ ## Collection controls
67
+
68
+ ```ts
69
+ const errorLog = init({
70
+ project: 'my-web',
71
+ endpoint: '/api/events', // your collector or a same-origin proxy
72
+ captureConsole: false,
73
+ beforeSend(event) {
74
+ if (event.message.includes('Expected diagnostic')) return null;
75
+ return event;
76
+ },
77
+ sanitizeUrl(url) {
78
+ return url.replace(/\/users\/[^/?#]+/g, '/users/:id');
79
+ },
80
+ shouldCaptureHttp(status) {
81
+ return status >= 500;
82
+ },
83
+ });
84
+ ```
85
+
86
+ By default, HTTP capture records 5xx responses and network failures, excludes intentional aborts, and excludes the collector endpoint. The SDK strips URL queries, fragments, and credentials and masks common email/token patterns. It does not collect request/response bodies, cookies, DOM, form inputs, or session recordings. Error text, URL paths, stacks, and custom context may still contain sensitive data; set application-specific filters. A failing `beforeSend` or `sanitizeUrl` drops the event.
87
+
88
+ For a custom `transport(batch, { signal })`, pass `signal` to your request and reject on delivery failure. Include `endpoint` for collector exclusion if you want automatic network capture; otherwise network capture is disabled for a custom transport. The default transport omits credentials.
89
+
90
+ ## Delivery limits
91
+
92
+ The default queue holds 50 events and flushes every 10 seconds. Batches contain up to 20 events or 48,000 bytes. Each attempt has a 5-second deadline; retryable failures get up to two retries. `maxQueueSize`, `flushIntervalMs`, and `transportTimeoutMs` are configurable within bounded ranges. These are best-effort limits: offline operation, tab closure, buffer overflow, or exhausted retries can lose events. There is no persistent offline queue or exactly-once guarantee.
93
+
94
+ ## Hosting and costs
95
+
96
+ This project distributes software, not a managed monitoring service. Infrastructure is not included. Hosting, servers, databases, storage, bandwidth, domains, backups, and third-party services are selected and paid for by each operator. Any charges are billed independently by their providers, not by this project or its maintainers. Self-hosting does not mean that your infrastructure is free.
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var S=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var P=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var H=(r,e,t)=>e in r?S(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var X=(r,e)=>{for(var t in e)S(r,t,{get:e[t],enumerable:!0})},D=(r,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of P(e))!z.call(r,o)&&o!==t&&S(r,o,{get:()=>e[o],enumerable:!(n=O(e,o))||n.enumerable});return r};var V=r=>D(S({},"__esModule",{value:!0}),r);var s=(r,e,t)=>H(r,typeof e!="symbol"?e+"":e,t);var ne={};X(ne,{init:()=>te});module.exports=V(ne);var q=[250,500],F=/(?:password|passwd|token|secret|authorization|cookie|session|api.?key|credential|bearer|private.?key)/i,M=new Set(["javascript","promise","react","console","http","network","manual"]),_=new Set(["browser","webview-ios","webview-android","unknown"]),Y=0;function c(r,e){try{return r==null?void 0:Reflect.get(Object(r),e)}catch{return}}function m(r){try{return String(r)}catch{return"[unavailable]"}}function W(r,e){return m(r).slice(0,e)}function w(){try{return performance.now()}catch{return Date.now()}}function N(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`${Date.now().toString(36)}-${(++Y).toString(36)}-${Math.random().toString(36).slice(2,10)}`}function x(r,e){try{if(e?.aborted)return!0}catch{}return c(r,"name")==="AbortError"||c(r,"code")===20}function U(r){if(r==null)return{message:"Unknown error"};let e=c(r,"message"),t=c(r,"name"),n=c(r,"stack");return{message:e==null?m(r):m(e),...t==null?{}:{name:m(t)},...n==null?{}:{stack:m(n)}}}function C(r){return new TextEncoder().encode(r).length}function b(r,e,t,n){return typeof r=="number"&&Number.isFinite(r)?Math.min(t,Math.max(e,Math.floor(r))):n}var A=class extends Error{constructor(t){super(`Collector responded ${t}`);s(this,"status",t)}},k=class extends Error{},B=class{constructor(e){s(this,"active");s(this,"endpoint");s(this,"options");s(this,"networkCaptureEnabled");s(this,"transportTimeoutMs");s(this,"startedAt",w());s(this,"viewId",N());s(this,"seenErrors",new WeakSet);s(this,"queue",[]);s(this,"maxQueueSize");s(this,"cancelWaits",new Set);s(this,"controllers",new Set);s(this,"destroySignal");s(this,"resolveDestroy");s(this,"interval");s(this,"flushing");s(this,"sequence",0);s(this,"inFlight",0);s(this,"sent",0);s(this,"dropped",0);s(this,"destroyed",!1);s(this,"onError",e=>{this.captureException(e.error??e.message??"Script error",{type:"javascript"})});s(this,"onRejection",e=>{this.captureException(e.reason,{type:"promise"})});s(this,"onVisibility",()=>{document.visibilityState==="hidden"&&this.tryBeacon()});if(this.options=e,this.active=e.enabled!==!1&&typeof window<"u"&&typeof document<"u",this.networkCaptureEnabled=e.captureNetwork!==!1&&(!e.transport||!!e.endpoint),this.maxQueueSize=b(e.maxQueueSize,1,100,50),this.transportTimeoutMs=b(e.transportTimeoutMs,250,6e4,5e3),this.destroySignal=new Promise(t=>{this.resolveDestroy=t}),!!this.active){if(!e.project||typeof e.project!="string")throw new Error("project is required");if(!e.transport&&!e.endpoint)throw new Error("endpoint or transport is required");this.endpoint=e.endpoint?this.absoluteUrl(e.endpoint):void 0,window.addEventListener("error",this.onError),window.addEventListener("unhandledrejection",this.onRejection),document.addEventListener("visibilitychange",this.onVisibility),this.networkCaptureEnabled&&Q(this),e.captureConsole===!0&&Z(this),this.interval=setInterval(()=>{this.flush()},b(e.flushIntervalMs,10,6e4,1e4))}}captureException(e,t={}){if(!(!this.active||this.destroyed||x(e)))try{if(e!==null&&(typeof e=="object"||typeof e=="function")&&this.seenErrors.has(e))return;let n=U(e),o=M.has(t.type)?t.type:"manual",i=this.makeEvent(o,n.message,{name:n.name,stack:n.stack,componentStack:t.componentStack,context:t.context});this.enqueue(i)&&e!==null&&(typeof e=="object"||typeof e=="function")&&this.seenErrors.add(e)}catch(n){n instanceof k&&this.dropped++}}reportNetwork(e,t,n,o,i){if(!(this.destroyed||!this.active||this.isCollectorUrl(t)||x(i)))try{if(n!==void 0&&!(this.options.shouldCaptureHttp?this.options.shouldCaptureHttp(n,t,e):n>=500))return;let a={method:W(e||"GET",16).toUpperCase(),url:t,status:n,durationMs:o},d=i===void 0?void 0:U(i),l=this.makeEvent(n===void 0?"network":"http",n===void 0?d?.message||"Network request failed":`HTTP ${n}`,{name:d?.name,network:a});this.enqueue(l)}catch{this.dropped++}}captureConsole(e){if(!(!this.active||this.destroyed))try{this.enqueue(this.makeEvent("console",e.map(m).join(" ")))}catch{this.dropped++}}flush(){return!this.active||this.destroyed?Promise.resolve():this.flushing?this.flushing:(this.flushing=this.drain().finally(()=>{this.flushing=void 0}),this.flushing)}destroy(){if(!this.destroyed){this.destroyed=!0,this.interval&&clearInterval(this.interval),this.active&&(window.removeEventListener("error",this.onError),window.removeEventListener("unhandledrejection",this.onRejection),document.removeEventListener("visibilitychange",this.onVisibility),this.networkCaptureEnabled&&$(this),this.options.captureConsole===!0&&K(this)),this.dropped+=this.queue.length+this.inFlight,this.queue.length=0;for(let e of this.cancelWaits)e();for(let e of this.controllers)e.abort();this.resolveDestroy(I)}}getStats(){return{queued:this.queue.length,sent:this.sent,dropped:this.dropped}}absoluteUrl(e){try{return new URL(e,window.location.href).href}catch{return e}}isCollectorUrl(e){if(!this.endpoint)return!1;try{let t=new URL(e,window.location.href),n=new URL(this.endpoint,window.location.href);return t.origin===n.origin&&t.pathname===n.pathname}catch{return e===this.endpoint}}cleanUrl(e){let t=m(e);if(this.options.sanitizeUrl){try{t=this.options.sanitizeUrl(t)}catch{throw new k("URL sanitizer failed")}if(typeof t!="string"||!t)throw new k("URL sanitizer returned no URL")}try{let n=new URL(t,window.location.href);return n.protocol!=="http:"&&n.protocol!=="https:"?"[unsupported URL]":(n.username="",n.password="",n.search="",n.hash="",this.cleanText(n.href,1024,!1))}catch{return this.cleanText(t,1024,!1).split(/[?#]/,1)[0]}}cleanText(e,t,n=!0){let o=m(e);return n&&(o=o.replace(/https?:\/\/[^\s<>"'()[\]]+/gi,i=>this.cleanUrl(i))),o.replace(/\bBearer\s+[A-Za-z0-9._~+\/-]+/gi,"Bearer [REDACTED]").replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi,"[REDACTED_EMAIL]").slice(0,t)}cleanContext(e){if(!e||typeof e!="object")return;let t={},n;try{n=Object.keys(e)}catch{return}for(let o of n){if(Object.keys(t).length>=12)break;if(F.test(o))continue;let i=c(e,o),a=this.cleanText(o,80);typeof i=="string"?t[a]=this.cleanText(i,500):(typeof i=="number"&&Number.isFinite(i)||typeof i=="boolean"||i===null)&&(t[a]=i)}return Object.keys(t).length?t:void 0}cleanNetwork(e){if(!e||typeof e!="object")return;let t=c(e,"status"),n=typeof t=="number"&&Number.isInteger(t)&&t>=100&&t<=599?t:void 0;return{method:this.cleanText(c(e,"method")??"GET",16).toUpperCase(),url:this.cleanUrl(c(e,"url")??""),...n===void 0?{}:{status:n},durationMs:b(c(e,"durationMs"),0,36e5,0)}}makeEvent(e,t,n={}){let o=c(navigator,"userAgent"),i=this.cleanContext(n.context),a=this.cleanNetwork(n.network);return{schemaVersion:1,eventId:N(),project:this.cleanText(this.options.project,80),environment:this.cleanText(this.options.environment??"development",80),release:this.cleanText(this.options.release??"unknown",120),sdkVersion:"0.1.0",occurredAt:new Date().toISOString(),viewId:this.viewId,sequence:++this.sequence,elapsedMs:b(w()-this.startedAt,0,36e5,0),type:e,message:this.cleanText(t,1024),...n.name===void 0?{}:{name:this.cleanText(n.name,100)},...n.stack===void 0?{}:{stack:this.cleanText(n.stack,4096)},...n.componentStack===void 0?{}:{componentStack:this.cleanText(n.componentStack,2048)},page:this.cleanUrl(window.location.href),runtime:_.has(this.options.runtime)?this.options.runtime:"browser",...typeof o=="string"?{browser:this.cleanText(o,300)}:{},...i?{context:i}:{},...a?{network:a}:{}}}sanitizeReplacement(e,t){let n=c(e,"type"),o=c(e,"runtime"),i=c(e,"name"),a=c(e,"stack"),d=c(e,"componentStack"),l=c(e,"browser"),u=this.cleanContext(c(e,"context")),p=this.cleanNetwork(c(e,"network"));return{...t,type:M.has(n)?n:t.type,message:this.cleanText(c(e,"message")??t.message,1024),...i===void 0?{name:t.name}:{name:this.cleanText(i,100)},...a===void 0?{stack:t.stack}:{stack:this.cleanText(a,4096)},...d===void 0?{componentStack:t.componentStack}:{componentStack:this.cleanText(d,2048)},page:this.cleanUrl(c(e,"page")??t.page),runtime:_.has(o)?o:t.runtime,...l===void 0?{browser:t.browser}:{browser:this.cleanText(l,300)},...u?{context:u}:{context:void 0},...p?{network:p}:{network:void 0}}}enqueue(e){if(this.destroyed)return!1;let t=e;if(this.options.beforeSend)try{let n={...e,context:e.context&&{...e.context},network:e.network&&{...e.network}},o=this.options.beforeSend(n);if(o===!1||o===null)return!1;t=this.sanitizeReplacement(o===void 0?n:o,e)}catch{return this.dropped++,!1}return C(JSON.stringify(t))>48e3?(this.dropped++,!1):(this.queue.length>=this.maxQueueSize&&(this.queue.shift(),this.dropped++),this.queue.push(t),this.queue.length>=this.maxQueueSize&&this.flush(),!0)}takeBatch(e=20,t=48e3){let n=[],o=C('{"schemaVersion":1,"events":[]}');for(;this.queue.length&&n.length<e;){let i=this.queue[0],a=C(JSON.stringify(i))+(n.length?1:0);if(n.length&&o+a>t)break;if(!n.length&&o+a>t){this.queue.shift(),this.dropped++;continue}n.push(this.queue.shift()),o+=a}return{schemaVersion:1,events:n}}async drain(){for(;!this.destroyed&&this.queue.length;){let e=this.takeBatch();if(e.events.length){this.inFlight+=e.events.length;try{await this.sendWithRetry(e)}finally{this.inFlight-=e.events.length}}}}async sendWithRetry(e){for(let t=0;t<=q.length&&!this.destroyed;t++){let n=new AbortController;this.controllers.add(n);let o,i=new Promise((d,l)=>{o=setTimeout(()=>{n.abort(),l(new Error("Collector transport timed out"))},this.transportTimeoutMs)}),a;try{if(await Promise.race([this.send(e,n.signal),i,this.destroySignal])===I||this.destroyed)return;this.sent+=e.events.length;return}catch(d){if(this.destroyed)return;let l=c(d,"status");if(!(typeof l!="number"||l===429||l>=500)||t===q.length)break;a=q[t]}finally{o&&clearTimeout(o),this.controllers.delete(n)}a!==void 0&&await this.wait(a)}this.destroyed||(this.dropped+=e.events.length)}async send(e,t){if(this.options.transport){await this.options.transport(e,{signal:t});return}let n=await window.fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),credentials:"omit",signal:t});if(!n.ok)throw new A(n.status)}wait(e){return new Promise(t=>{let n=()=>{clearTimeout(o),this.cancelWaits.delete(n),t()},o=setTimeout(n,e);this.cancelWaits.add(n)})}tryBeacon(){if(!(this.destroyed||this.options.transport||!this.endpoint||!this.queue.length))try{let e=new URL(this.endpoint);if(e.origin!==window.location.origin||e.search||e.hash||e.username||e.password||typeof navigator.sendBeacon!="function")return;let t=this.queue.slice(0,10);for(;t.length>0;){let o=JSON.stringify({schemaVersion:1,events:t});if(C(o)<=24e3){navigator.sendBeacon(this.endpoint,new Blob([o],{type:"application/json"}))&&this.queue.splice(0,t.length);return}t.pop()}}catch{}}},I=Symbol("destroyed"),T,R;function Q(r){T||(T=J()),T.clients.add(r)}function $(r){let e=T;e&&(e.clients.delete(r),e.clients.size||(e.cleanup(),T=void 0))}function G(r,e){let t=typeof Request<"u"&&r instanceof Request?r:void 0;return{url:t?t.url:m(r),method:m(e?.method??t?.method??"GET"),signal:e?.signal??t?.signal}}function J(){let r=new Set,e=window.fetch,t;typeof e=="function"&&(t=function(...u){if(!r.size)return Reflect.apply(e,this,u);let p=w(),f;try{f=G(u[0],u[1])}catch{f={url:"",method:"GET"}}let g;try{g=Reflect.apply(e,this,u)}catch(h){if(!x(h,f.signal))for(let v of r)v.reportNetwork(f.method,f.url,void 0,w()-p,h);throw h}return g.then(h=>{try{let v=h.status;for(let y of r)y.reportNetwork(f.method,f.url,v,w()-p)}catch{}return h},h=>{if(!x(h,f.signal))for(let v of r)v.reportNetwork(f.method,f.url,void 0,w()-p,h);throw h})},window.fetch=t);let n=typeof XMLHttpRequest>"u"?void 0:XMLHttpRequest.prototype,o=n?.open,i=n?.send,a=new WeakMap,d,l;return n&&o&&i&&(d=(function(...u){let p=Reflect.apply(o,this,u);try{a.set(this,{method:m(u[0]),url:m(u[1])})}catch{}return p}),l=function(...u){if(!r.size)return Reflect.apply(i,this,u);let p=a.get(this);if(!p)return Reflect.apply(i,this,u);let f=w(),g=!1,h=!1,v=()=>{g=!0},y=()=>{h=!0},L=()=>{if(this.removeEventListener("abort",v),this.removeEventListener("error",y),this.removeEventListener("timeout",y),this.removeEventListener("loadend",L),!g)try{let E=this.status;if(E===0&&!h)return;for(let j of r)j.reportNetwork(p.method,p.url,E===0?void 0:E,w()-f)}catch{}};try{this.addEventListener("abort",v),this.addEventListener("error",y),this.addEventListener("timeout",y),this.addEventListener("loadend",L)}catch{return Reflect.apply(i,this,u)}try{return Reflect.apply(i,this,u)}catch(E){throw this.removeEventListener("abort",v),this.removeEventListener("error",y),this.removeEventListener("timeout",y),this.removeEventListener("loadend",L),E}},n.open=d,n.send=l),{clients:r,cleanup(){t&&window.fetch===t&&(window.fetch=e),n&&d&&n.open===d&&(n.open=o),n&&l&&n.send===l&&(n.send=i)}}}function Z(r){R||(R=ee()),R.clients.add(r)}function K(r){let e=R;e&&(e.clients.delete(r),e.clients.size||(e.cleanup(),R=void 0))}function ee(){let r=new Set,e=console.error,t=function(...n){try{return Reflect.apply(e,this,n)}finally{for(let o of r)o.captureConsole(n)}};return console.error=t,{clients:r,cleanup(){console.error===t&&(console.error=e)}}}function te(r){return new B(r)}
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["import type { ErrorEventRecord, EventBatch, EventType, Runtime } from 'browser-error-log-protocol';\n\nexport type { ErrorEventRecord, EventBatch } from 'browser-error-log-protocol';\n\nexport interface CaptureExtra {\n type?: EventType;\n context?: Record<string, unknown>;\n componentStack?: string;\n}\n\nexport interface TransportContext { signal: AbortSignal }\n\nexport interface BrowserErrorLogOptions {\n project: string;\n environment?: string;\n release?: string;\n endpoint?: string;\n transport?: (batch: EventBatch, context: TransportContext) => void | Promise<void>;\n runtime?: Runtime;\n enabled?: boolean;\n captureConsole?: boolean;\n /** Defaults to true. With a custom transport, automatic network capture requires endpoint for collector exclusion. */\n captureNetwork?: boolean;\n beforeSend?: (event: ErrorEventRecord) => ErrorEventRecord | false | null | void;\n sanitizeUrl?: (url: string) => string;\n shouldCaptureHttp?: (status: number, url: string, method: string) => boolean;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n /** Per-attempt deadline, clamped to 250\u201360000 ms; defaults to 5000 ms. */\n transportTimeoutMs?: number;\n}\n\nexport interface BrowserErrorLogClient {\n captureException(error: unknown, extra?: CaptureExtra): void;\n flush(): Promise<void>;\n destroy(): void;\n getStats(): { queued: number; sent: number; dropped: number };\n}\n\nconst MAX_BATCH_EVENTS = 20;\nconst MAX_BATCH_BYTES = 48_000;\nconst MAX_BEACON_EVENTS = 10;\nconst MAX_BEACON_BYTES = 24_000;\nconst RETRY_DELAYS_MS = [250, 500];\nconst SENSITIVE_KEY = /(?:password|passwd|token|secret|authorization|cookie|session|api.?key|credential|bearer|private.?key)/i;\nconst EVENT_TYPES = new Set<EventType>(['javascript', 'promise', 'react', 'console', 'http', 'network', 'manual']);\nconst RUNTIMES = new Set<Runtime>(['browser', 'webview-ios', 'webview-android', 'unknown']);\nlet fallbackId = 0;\n\nfunction read(object: unknown, key: PropertyKey): unknown {\n try { return object == null ? undefined : Reflect.get(Object(object), key); }\n catch { return undefined; }\n}\n\nfunction safeString(value: unknown): string {\n try { return String(value); }\n catch { return '[unavailable]'; }\n}\n\nfunction trim(value: unknown, length: number): string {\n return safeString(value).slice(0, length);\n}\n\nfunction now(): number {\n try { return performance.now(); }\n catch { return Date.now(); }\n}\n\nfunction newId(): string {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n } catch { /* fall through */ }\n return `${Date.now().toString(36)}-${(++fallbackId).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction isAbort(error: unknown, signal?: AbortSignal | null): boolean {\n try { if (signal?.aborted) return true; }\n catch { /* ignore hostile signal */ }\n return read(error, 'name') === 'AbortError' || read(error, 'code') === 20;\n}\n\nfunction errorFields(error: unknown): { message: string; name?: string; stack?: string } {\n if (error === null || error === undefined) return { message: 'Unknown error' };\n const message = read(error, 'message');\n const name = read(error, 'name');\n const stack = read(error, 'stack');\n return {\n message: message == null ? safeString(error) : safeString(message),\n ...(name == null ? {} : { name: safeString(name) }),\n ...(stack == null ? {} : { stack: safeString(stack) }),\n };\n}\n\nfunction byteLength(value: string): number {\n return new TextEncoder().encode(value).length;\n}\n\nfunction boundedNumber(value: unknown, minimum: number, maximum: number, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value)\n ? Math.min(maximum, Math.max(minimum, Math.floor(value)))\n : fallback;\n}\n\nclass HttpDeliveryError extends Error {\n constructor(readonly status: number) { super(`Collector responded ${status}`); }\n}\n\nclass UrlSanitizationError extends Error {}\n\nclass Client implements BrowserErrorLogClient {\n private readonly active: boolean;\n private readonly endpoint?: string;\n private readonly options: BrowserErrorLogOptions;\n private readonly networkCaptureEnabled: boolean;\n private readonly transportTimeoutMs: number;\n private readonly startedAt = now();\n private readonly viewId = newId();\n private readonly seenErrors = new WeakSet<object>();\n private readonly queue: ErrorEventRecord[] = [];\n private readonly maxQueueSize: number;\n private readonly cancelWaits = new Set<() => void>();\n private readonly controllers = new Set<AbortController>();\n private readonly destroySignal: Promise<symbol>;\n private resolveDestroy!: (value: symbol) => void;\n private interval?: ReturnType<typeof setInterval>;\n private flushing?: Promise<void>;\n private sequence = 0;\n private inFlight = 0;\n private sent = 0;\n private dropped = 0;\n private destroyed = false;\n\n constructor(options: BrowserErrorLogOptions) {\n this.options = options;\n this.active = options.enabled !== false && typeof window !== 'undefined' && typeof document !== 'undefined';\n this.networkCaptureEnabled = options.captureNetwork !== false && (!options.transport || Boolean(options.endpoint));\n this.maxQueueSize = boundedNumber(options.maxQueueSize, 1, 100, 50);\n this.transportTimeoutMs = boundedNumber(options.transportTimeoutMs, 250, 60_000, 5_000);\n this.destroySignal = new Promise(resolve => { this.resolveDestroy = resolve; });\n if (!this.active) return;\n if (!options.project || typeof options.project !== 'string') throw new Error('project is required');\n if (!options.transport && !options.endpoint) throw new Error('endpoint or transport is required');\n this.endpoint = options.endpoint ? this.absoluteUrl(options.endpoint) : undefined;\n window.addEventListener('error', this.onError);\n window.addEventListener('unhandledrejection', this.onRejection);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (this.networkCaptureEnabled) addNetworkClient(this);\n if (options.captureConsole === true) addConsoleClient(this);\n this.interval = setInterval(() => { void this.flush(); }, boundedNumber(options.flushIntervalMs, 10, 60_000, 10_000));\n }\n\n captureException(error: unknown, extra: CaptureExtra = {}): void {\n if (!this.active || this.destroyed || isAbort(error)) return;\n try {\n if (error !== null && (typeof error === 'object' || typeof error === 'function')) {\n if (this.seenErrors.has(error)) return;\n }\n const fields = errorFields(error);\n const type = EVENT_TYPES.has(extra.type as EventType) ? extra.type! : 'manual';\n const event = this.makeEvent(type, fields.message, {\n name: fields.name,\n stack: fields.stack,\n componentStack: extra.componentStack,\n context: extra.context,\n });\n if (this.enqueue(event) && error !== null && (typeof error === 'object' || typeof error === 'function')) {\n this.seenErrors.add(error);\n }\n } catch (error) {\n if (error instanceof UrlSanitizationError) this.dropped++;\n // Diagnostics must never affect the host app.\n }\n }\n\n reportNetwork(method: string, url: string, status: number | undefined, durationMs: number, failure?: unknown): void {\n if (this.destroyed || !this.active || this.isCollectorUrl(url) || isAbort(failure)) return;\n try {\n if (status !== undefined) {\n const include = this.options.shouldCaptureHttp\n ? this.options.shouldCaptureHttp(status, url, method)\n : status >= 500;\n if (!include) return;\n }\n const network = { method: trim(method || 'GET', 16).toUpperCase(), url, status, durationMs };\n const fields = failure === undefined ? undefined : errorFields(failure);\n const event = this.makeEvent(status === undefined ? 'network' : 'http',\n status === undefined ? (fields?.message || 'Network request failed') : `HTTP ${status}`,\n { name: fields?.name, network });\n this.enqueue(event);\n } catch { this.dropped++; /* a failing hook must not expose an unfiltered event */ }\n }\n\n captureConsole(values: unknown[]): void {\n if (!this.active || this.destroyed) return;\n try { this.enqueue(this.makeEvent('console', values.map(safeString).join(' '))); }\n catch { this.dropped++; /* console behavior is never changed by capture */ }\n }\n\n flush(): Promise<void> {\n if (!this.active || this.destroyed) return Promise.resolve();\n if (this.flushing) return this.flushing;\n this.flushing = this.drain().finally(() => { this.flushing = undefined; });\n return this.flushing;\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n if (this.interval) clearInterval(this.interval);\n if (this.active) {\n window.removeEventListener('error', this.onError);\n window.removeEventListener('unhandledrejection', this.onRejection);\n document.removeEventListener('visibilitychange', this.onVisibility);\n if (this.networkCaptureEnabled) removeNetworkClient(this);\n if (this.options.captureConsole === true) removeConsoleClient(this);\n }\n this.dropped += this.queue.length + this.inFlight;\n this.queue.length = 0;\n for (const cancel of this.cancelWaits) cancel();\n for (const controller of this.controllers) controller.abort();\n this.resolveDestroy(DESTROYED);\n }\n\n getStats(): { queued: number; sent: number; dropped: number } {\n return { queued: this.queue.length, sent: this.sent, dropped: this.dropped };\n }\n\n private readonly onError = (event: ErrorEvent): void => {\n this.captureException(event.error ?? event.message ?? 'Script error', { type: 'javascript' });\n };\n\n private readonly onRejection = (event: PromiseRejectionEvent): void => {\n this.captureException(event.reason, { type: 'promise' });\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.tryBeacon();\n };\n\n private absoluteUrl(url: string): string {\n try { return new URL(url, window.location.href).href; }\n catch { return url; }\n }\n\n private isCollectorUrl(url: string): boolean {\n if (!this.endpoint) return false;\n try {\n const request = new URL(url, window.location.href);\n const collector = new URL(this.endpoint, window.location.href);\n return request.origin === collector.origin && request.pathname === collector.pathname;\n } catch { return url === this.endpoint; }\n }\n\n private cleanUrl(input: unknown): string {\n let value = safeString(input);\n if (this.options.sanitizeUrl) {\n try { value = this.options.sanitizeUrl(value); }\n catch { throw new UrlSanitizationError('URL sanitizer failed'); }\n if (typeof value !== 'string' || !value) throw new UrlSanitizationError('URL sanitizer returned no URL');\n }\n try {\n const url = new URL(value, window.location.href);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return '[unsupported URL]';\n url.username = '';\n url.password = '';\n url.search = '';\n url.hash = '';\n return this.cleanText(url.href, 1024, false);\n } catch { return this.cleanText(value, 1024, false).split(/[?#]/, 1)[0]; }\n }\n\n private cleanText(input: unknown, length: number, replaceUrls = true): string {\n let value = safeString(input);\n if (replaceUrls) {\n value = value.replace(/https?:\\/\\/[^\\s<>\"'()[\\]]+/gi, match => this.cleanUrl(match));\n }\n return value\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+\\/-]+/gi, 'Bearer [REDACTED]')\n .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/gi, '[REDACTED_EMAIL]')\n .slice(0, length);\n }\n\n private cleanContext(input: unknown): ErrorEventRecord['context'] {\n if (!input || typeof input !== 'object') return undefined;\n const output: NonNullable<ErrorEventRecord['context']> = {};\n let keys: string[];\n try { keys = Object.keys(input); }\n catch { return undefined; }\n for (const key of keys) {\n if (Object.keys(output).length >= 12) break;\n if (SENSITIVE_KEY.test(key)) continue;\n const value = read(input, key);\n const safeKey = this.cleanText(key, 80);\n if (typeof value === 'string') output[safeKey] = this.cleanText(value, 500);\n else if (typeof value === 'number' && Number.isFinite(value)) output[safeKey] = value;\n else if (typeof value === 'boolean' || value === null) output[safeKey] = value;\n }\n return Object.keys(output).length ? output : undefined;\n }\n\n private cleanNetwork(input: unknown): ErrorEventRecord['network'] {\n if (!input || typeof input !== 'object') return undefined;\n const rawStatus = read(input, 'status');\n const status = typeof rawStatus === 'number' && Number.isInteger(rawStatus) && rawStatus >= 100 && rawStatus <= 599\n ? rawStatus : undefined;\n return {\n method: this.cleanText(read(input, 'method') ?? 'GET', 16).toUpperCase(),\n url: this.cleanUrl(read(input, 'url') ?? ''),\n ...(status === undefined ? {} : { status }),\n durationMs: boundedNumber(read(input, 'durationMs'), 0, 3_600_000, 0),\n };\n }\n\n private makeEvent(type: EventType, message: string, extra: {\n name?: string; stack?: string; componentStack?: string;\n context?: unknown; network?: unknown;\n } = {}): ErrorEventRecord {\n const userAgent = read(navigator, 'userAgent');\n const context = this.cleanContext(extra.context);\n const network = this.cleanNetwork(extra.network);\n return {\n schemaVersion: 1,\n eventId: newId(),\n project: this.cleanText(this.options.project, 80),\n environment: this.cleanText(this.options.environment ?? 'development', 80),\n release: this.cleanText(this.options.release ?? 'unknown', 120),\n sdkVersion: '0.1.0',\n occurredAt: new Date().toISOString(),\n viewId: this.viewId,\n sequence: ++this.sequence,\n elapsedMs: boundedNumber(now() - this.startedAt, 0, 3_600_000, 0),\n type,\n message: this.cleanText(message, 1024),\n ...(extra.name === undefined ? {} : { name: this.cleanText(extra.name, 100) }),\n ...(extra.stack === undefined ? {} : { stack: this.cleanText(extra.stack, 4096) }),\n ...(extra.componentStack === undefined ? {} : { componentStack: this.cleanText(extra.componentStack, 2048) }),\n page: this.cleanUrl(window.location.href),\n runtime: RUNTIMES.has(this.options.runtime as Runtime) ? this.options.runtime! : 'browser',\n ...(typeof userAgent === 'string' ? { browser: this.cleanText(userAgent, 300) } : {}),\n ...(context ? { context } : {}),\n ...(network ? { network } : {}),\n };\n }\n\n private sanitizeReplacement(candidate: unknown, base: ErrorEventRecord): ErrorEventRecord {\n const type = read(candidate, 'type');\n const runtime = read(candidate, 'runtime');\n const name = read(candidate, 'name');\n const stack = read(candidate, 'stack');\n const componentStack = read(candidate, 'componentStack');\n const browser = read(candidate, 'browser');\n const context = this.cleanContext(read(candidate, 'context'));\n const network = this.cleanNetwork(read(candidate, 'network'));\n return {\n ...base,\n type: EVENT_TYPES.has(type as EventType) ? type as EventType : base.type,\n message: this.cleanText(read(candidate, 'message') ?? base.message, 1024),\n ...(name === undefined ? { name: base.name } : { name: this.cleanText(name, 100) }),\n ...(stack === undefined ? { stack: base.stack } : { stack: this.cleanText(stack, 4096) }),\n ...(componentStack === undefined ? { componentStack: base.componentStack } : { componentStack: this.cleanText(componentStack, 2048) }),\n page: this.cleanUrl(read(candidate, 'page') ?? base.page),\n runtime: RUNTIMES.has(runtime as Runtime) ? runtime as Runtime : base.runtime,\n ...(browser === undefined ? { browser: base.browser } : { browser: this.cleanText(browser, 300) }),\n ...(context ? { context } : { context: undefined }),\n ...(network ? { network } : { network: undefined }),\n };\n }\n\n private enqueue(event: ErrorEventRecord): boolean {\n if (this.destroyed) return false;\n let finalEvent = event;\n if (this.options.beforeSend) {\n try {\n const copy = { ...event, context: event.context && { ...event.context }, network: event.network && { ...event.network } };\n const result = this.options.beforeSend(copy);\n if (result === false || result === null) return false;\n finalEvent = this.sanitizeReplacement(result === undefined ? copy : result, event);\n } catch { this.dropped++; return false; }\n }\n // A single event can never make a batch exceed its byte budget.\n if (byteLength(JSON.stringify(finalEvent)) > MAX_BATCH_BYTES) { this.dropped++; return false; }\n if (this.queue.length >= this.maxQueueSize) { this.queue.shift(); this.dropped++; }\n this.queue.push(finalEvent);\n if (this.queue.length >= this.maxQueueSize) void this.flush();\n return true;\n }\n\n private takeBatch(maxEvents = MAX_BATCH_EVENTS, maxBytes = MAX_BATCH_BYTES): EventBatch {\n const events: ErrorEventRecord[] = [];\n let bytes = byteLength('{\"schemaVersion\":1,\"events\":[]}');\n while (this.queue.length && events.length < maxEvents) {\n const next = this.queue[0];\n const size = byteLength(JSON.stringify(next)) + (events.length ? 1 : 0);\n if (events.length && bytes + size > maxBytes) break;\n if (!events.length && bytes + size > maxBytes) { this.queue.shift(); this.dropped++; continue; }\n events.push(this.queue.shift()!);\n bytes += size;\n }\n return { schemaVersion: 1, events };\n }\n\n private async drain(): Promise<void> {\n while (!this.destroyed && this.queue.length) {\n const batch = this.takeBatch();\n if (batch.events.length) {\n this.inFlight += batch.events.length;\n try { await this.sendWithRetry(batch); }\n finally { this.inFlight -= batch.events.length; }\n }\n }\n }\n\n private async sendWithRetry(batch: EventBatch): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length && !this.destroyed; attempt++) {\n const controller = new AbortController();\n this.controllers.add(controller);\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_resolve, reject) => {\n timeoutHandle = setTimeout(() => {\n controller.abort();\n reject(new Error('Collector transport timed out'));\n }, this.transportTimeoutMs);\n });\n let retryDelay: number | undefined;\n try {\n const result = await Promise.race([this.send(batch, controller.signal), timeout, this.destroySignal]);\n if (result === DESTROYED || this.destroyed) return;\n this.sent += batch.events.length;\n return;\n } catch (error) {\n if (this.destroyed) return;\n const status = read(error, 'status');\n const retryable = typeof status !== 'number' || status === 429 || status >= 500;\n if (!retryable || attempt === RETRY_DELAYS_MS.length) break;\n retryDelay = RETRY_DELAYS_MS[attempt];\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n this.controllers.delete(controller);\n }\n if (retryDelay !== undefined) await this.wait(retryDelay);\n }\n if (!this.destroyed) this.dropped += batch.events.length;\n }\n\n private async send(batch: EventBatch, signal: AbortSignal): Promise<void> {\n if (this.options.transport) { await this.options.transport(batch, { signal }); return; }\n const response = await window.fetch(this.endpoint!, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(batch),\n credentials: 'omit',\n signal,\n });\n if (!response.ok) throw new HttpDeliveryError(response.status);\n }\n\n private wait(milliseconds: number): Promise<void> {\n return new Promise(resolve => {\n const finish = () => { clearTimeout(timer); this.cancelWaits.delete(finish); resolve(); };\n const timer = setTimeout(finish, milliseconds);\n this.cancelWaits.add(finish);\n });\n }\n\n private tryBeacon(): void {\n if (this.destroyed || this.options.transport || !this.endpoint || !this.queue.length) return;\n try {\n const url = new URL(this.endpoint);\n if (url.origin !== window.location.origin || url.search || url.hash || url.username || url.password) return;\n if (typeof navigator.sendBeacon !== 'function') return;\n const candidates = this.queue.slice(0, MAX_BEACON_EVENTS);\n while (candidates.length > 0) {\n const batch: EventBatch = { schemaVersion: 1, events: candidates };\n const body = JSON.stringify(batch);\n if (byteLength(body) <= MAX_BEACON_BYTES) {\n if (navigator.sendBeacon(this.endpoint, new Blob([body], { type: 'application/json' }))) {\n this.queue.splice(0, candidates.length);\n }\n return;\n }\n candidates.pop();\n }\n } catch { /* best effort only */ }\n }\n}\n\nconst DESTROYED = Symbol('destroyed');\n\ninterface Instrumentation {\n clients: Set<Client>;\n cleanup(): void;\n}\n\nlet networkInstrumentation: Instrumentation | undefined;\nlet consoleInstrumentation: Instrumentation | undefined;\n\nfunction addNetworkClient(client: Client): void {\n if (!networkInstrumentation) networkInstrumentation = installNetwork();\n networkInstrumentation.clients.add(client);\n}\n\nfunction removeNetworkClient(client: Client): void {\n const instrumentation = networkInstrumentation;\n if (!instrumentation) return;\n instrumentation.clients.delete(client);\n if (!instrumentation.clients.size) {\n instrumentation.cleanup();\n networkInstrumentation = undefined;\n }\n}\n\nfunction describeFetch(input: RequestInfo | URL, init?: RequestInit): { url: string; method: string; signal?: AbortSignal | null } {\n const request = typeof Request !== 'undefined' && input instanceof Request ? input : undefined;\n const url = request ? request.url : safeString(input);\n return { url, method: safeString(init?.method ?? request?.method ?? 'GET'), signal: init?.signal ?? request?.signal };\n}\n\nfunction installNetwork(): Instrumentation {\n const clients = new Set<Client>();\n const originalFetch = window.fetch;\n let wrappedFetch: typeof fetch | undefined;\n if (typeof originalFetch === 'function') {\n wrappedFetch = function (this: typeof window, ...args: Parameters<typeof fetch>): ReturnType<typeof fetch> {\n if (!clients.size) return Reflect.apply(originalFetch, this, args);\n const started = now();\n let request: ReturnType<typeof describeFetch>;\n try { request = describeFetch(args[0], args[1]); }\n catch { request = { url: '', method: 'GET' }; }\n let promise: ReturnType<typeof fetch>;\n try { promise = Reflect.apply(originalFetch, this, args); }\n catch (error) {\n if (!isAbort(error, request.signal)) for (const client of clients) client.reportNetwork(request.method, request.url, undefined, now() - started, error);\n throw error;\n }\n return promise.then(\n response => {\n try {\n const status = response.status;\n for (const client of clients) client.reportNetwork(request.method, request.url, status, now() - started);\n } catch { /* telemetry cannot change the fetch result */ }\n return response;\n },\n error => {\n if (!isAbort(error, request.signal)) for (const client of clients) client.reportNetwork(request.method, request.url, undefined, now() - started, error);\n throw error;\n },\n );\n };\n window.fetch = wrappedFetch;\n }\n\n const prototype = typeof XMLHttpRequest === 'undefined' ? undefined : XMLHttpRequest.prototype;\n const originalOpen = prototype?.open;\n const originalSend = prototype?.send;\n const metadata = new WeakMap<XMLHttpRequest, { method: string; url: string }>();\n let wrappedOpen: typeof XMLHttpRequest.prototype.open | undefined;\n let wrappedSend: typeof XMLHttpRequest.prototype.send | undefined;\n if (prototype && originalOpen && originalSend) {\n wrappedOpen = (function (this: XMLHttpRequest, ...args: unknown[]): void {\n const result = Reflect.apply(originalOpen, this, args);\n try { metadata.set(this, { method: safeString(args[0]), url: safeString(args[1]) }); }\n catch { /* native open already succeeded */ }\n return result;\n }) as typeof XMLHttpRequest.prototype.open;\n wrappedSend = function (this: XMLHttpRequest, ...args: Parameters<XMLHttpRequest['send']>): void {\n if (!clients.size) return Reflect.apply(originalSend, this, args);\n const details = metadata.get(this);\n if (!details) return Reflect.apply(originalSend, this, args);\n const started = now();\n let aborted = false;\n let failed = false;\n const onAbort = () => { aborted = true; };\n const onFailure = () => { failed = true; };\n const onLoadEnd = () => {\n this.removeEventListener('abort', onAbort);\n this.removeEventListener('error', onFailure);\n this.removeEventListener('timeout', onFailure);\n this.removeEventListener('loadend', onLoadEnd);\n if (aborted) return;\n try {\n const status = this.status;\n if (status === 0 && !failed) return;\n for (const client of clients) client.reportNetwork(details.method, details.url,\n status === 0 ? undefined : status, now() - started);\n } catch { /* XHR state may be unavailable */ }\n };\n try {\n this.addEventListener('abort', onAbort);\n this.addEventListener('error', onFailure);\n this.addEventListener('timeout', onFailure);\n this.addEventListener('loadend', onLoadEnd);\n } catch { return Reflect.apply(originalSend, this, args); }\n try { return Reflect.apply(originalSend, this, args); }\n catch (error) {\n this.removeEventListener('abort', onAbort);\n this.removeEventListener('error', onFailure);\n this.removeEventListener('timeout', onFailure);\n this.removeEventListener('loadend', onLoadEnd);\n throw error;\n }\n };\n prototype.open = wrappedOpen!;\n prototype.send = wrappedSend;\n }\n return {\n clients,\n cleanup() {\n if (wrappedFetch && window.fetch === wrappedFetch) window.fetch = originalFetch;\n if (prototype && wrappedOpen && prototype.open === wrappedOpen) prototype.open = originalOpen!;\n if (prototype && wrappedSend && prototype.send === wrappedSend) prototype.send = originalSend!;\n },\n };\n}\n\nfunction addConsoleClient(client: Client): void {\n if (!consoleInstrumentation) consoleInstrumentation = installConsole();\n consoleInstrumentation.clients.add(client);\n}\n\nfunction removeConsoleClient(client: Client): void {\n const instrumentation = consoleInstrumentation;\n if (!instrumentation) return;\n instrumentation.clients.delete(client);\n if (!instrumentation.clients.size) {\n instrumentation.cleanup();\n consoleInstrumentation = undefined;\n }\n}\n\nfunction installConsole(): Instrumentation {\n const clients = new Set<Client>();\n const original = console.error;\n const wrapped: typeof console.error = function (this: Console, ...values: unknown[]): void {\n try { return Reflect.apply(original, this, values); }\n finally { for (const client of clients) client.captureConsole(values); }\n };\n console.error = wrapped;\n return { clients, cleanup() { if (console.error === wrapped) console.error = original; } };\n}\n\nexport function init(options: BrowserErrorLogOptions): BrowserErrorLogClient {\n return new Client(options);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "init", "__toCommonJS", "RETRY_DELAYS_MS", "SENSITIVE_KEY", "EVENT_TYPES", "RUNTIMES", "fallbackId", "read", "object", "key", "safeString", "value", "trim", "length", "now", "newId", "isAbort", "error", "signal", "errorFields", "message", "name", "stack", "byteLength", "boundedNumber", "minimum", "maximum", "fallback", "HttpDeliveryError", "status", "__publicField", "UrlSanitizationError", "Client", "options", "event", "resolve", "addNetworkClient", "addConsoleClient", "extra", "fields", "type", "method", "url", "durationMs", "failure", "network", "values", "removeNetworkClient", "removeConsoleClient", "cancel", "controller", "DESTROYED", "request", "collector", "input", "replaceUrls", "match", "output", "keys", "safeKey", "rawStatus", "userAgent", "context", "candidate", "base", "runtime", "componentStack", "browser", "finalEvent", "copy", "result", "maxEvents", "maxBytes", "events", "bytes", "next", "size", "batch", "attempt", "timeoutHandle", "timeout", "_resolve", "reject", "retryDelay", "response", "milliseconds", "finish", "timer", "candidates", "body", "networkInstrumentation", "consoleInstrumentation", "client", "installNetwork", "instrumentation", "describeFetch", "init", "clients", "originalFetch", "wrappedFetch", "args", "started", "promise", "prototype", "originalOpen", "originalSend", "metadata", "wrappedOpen", "wrappedSend", "details", "aborted", "failed", "onAbort", "onFailure", "onLoadEnd", "installConsole", "original", "wrapped"]
7
+ }
@@ -0,0 +1,41 @@
1
+ import type { ErrorEventRecord, EventBatch, EventType, Runtime } from 'browser-error-log-protocol';
2
+ export type { ErrorEventRecord, EventBatch } from 'browser-error-log-protocol';
3
+ export interface CaptureExtra {
4
+ type?: EventType;
5
+ context?: Record<string, unknown>;
6
+ componentStack?: string;
7
+ }
8
+ export interface TransportContext {
9
+ signal: AbortSignal;
10
+ }
11
+ export interface BrowserErrorLogOptions {
12
+ project: string;
13
+ environment?: string;
14
+ release?: string;
15
+ endpoint?: string;
16
+ transport?: (batch: EventBatch, context: TransportContext) => void | Promise<void>;
17
+ runtime?: Runtime;
18
+ enabled?: boolean;
19
+ captureConsole?: boolean;
20
+ /** Defaults to true. With a custom transport, automatic network capture requires endpoint for collector exclusion. */
21
+ captureNetwork?: boolean;
22
+ beforeSend?: (event: ErrorEventRecord) => ErrorEventRecord | false | null | void;
23
+ sanitizeUrl?: (url: string) => string;
24
+ shouldCaptureHttp?: (status: number, url: string, method: string) => boolean;
25
+ flushIntervalMs?: number;
26
+ maxQueueSize?: number;
27
+ /** Per-attempt deadline, clamped to 250–60000 ms; defaults to 5000 ms. */
28
+ transportTimeoutMs?: number;
29
+ }
30
+ export interface BrowserErrorLogClient {
31
+ captureException(error: unknown, extra?: CaptureExtra): void;
32
+ flush(): Promise<void>;
33
+ destroy(): void;
34
+ getStats(): {
35
+ queued: number;
36
+ sent: number;
37
+ dropped: number;
38
+ };
39
+ }
40
+ export declare function init(options: BrowserErrorLogOptions): BrowserErrorLogClient;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/browser/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAEnG,YAAY,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE/E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,gBAAgB;IAAG,MAAM,EAAE,WAAW,CAAA;CAAE;AAEzD,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,sHAAsH;IACtH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,gBAAgB,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;IACjF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAC7E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,gBAAgB,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IAC7D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;IAChB,QAAQ,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/D;AA2lBD,wBAAgB,IAAI,CAAC,OAAO,EAAE,sBAAsB,GAAG,qBAAqB,CAE3E"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ var j=Object.defineProperty;var O=(r,e,t)=>e in r?j(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var s=(r,e,t)=>O(r,typeof e!="symbol"?e+"":e,t);var L=[250,500],P=/(?:password|passwd|token|secret|authorization|cookie|session|api.?key|credential|bearer|private.?key)/i,B=new Set(["javascript","promise","react","console","http","network","manual"]),M=new Set(["browser","webview-ios","webview-android","unknown"]),z=0;function c(r,e){try{return r==null?void 0:Reflect.get(Object(r),e)}catch{return}}function m(r){try{return String(r)}catch{return"[unavailable]"}}function H(r,e){return m(r).slice(0,e)}function w(){try{return performance.now()}catch{return Date.now()}}function _(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return`${Date.now().toString(36)}-${(++z).toString(36)}-${Math.random().toString(36).slice(2,10)}`}function C(r,e){try{if(e?.aborted)return!0}catch{}return c(r,"name")==="AbortError"||c(r,"code")===20}function N(r){if(r==null)return{message:"Unknown error"};let e=c(r,"message"),t=c(r,"name"),n=c(r,"stack");return{message:e==null?m(r):m(e),...t==null?{}:{name:m(t)},...n==null?{}:{stack:m(n)}}}function S(r){return new TextEncoder().encode(r).length}function b(r,e,t,n){return typeof r=="number"&&Number.isFinite(r)?Math.min(t,Math.max(e,Math.floor(r))):n}var q=class extends Error{constructor(t){super(`Collector responded ${t}`);s(this,"status",t)}},k=class extends Error{},A=class{constructor(e){s(this,"active");s(this,"endpoint");s(this,"options");s(this,"networkCaptureEnabled");s(this,"transportTimeoutMs");s(this,"startedAt",w());s(this,"viewId",_());s(this,"seenErrors",new WeakSet);s(this,"queue",[]);s(this,"maxQueueSize");s(this,"cancelWaits",new Set);s(this,"controllers",new Set);s(this,"destroySignal");s(this,"resolveDestroy");s(this,"interval");s(this,"flushing");s(this,"sequence",0);s(this,"inFlight",0);s(this,"sent",0);s(this,"dropped",0);s(this,"destroyed",!1);s(this,"onError",e=>{this.captureException(e.error??e.message??"Script error",{type:"javascript"})});s(this,"onRejection",e=>{this.captureException(e.reason,{type:"promise"})});s(this,"onVisibility",()=>{document.visibilityState==="hidden"&&this.tryBeacon()});if(this.options=e,this.active=e.enabled!==!1&&typeof window<"u"&&typeof document<"u",this.networkCaptureEnabled=e.captureNetwork!==!1&&(!e.transport||!!e.endpoint),this.maxQueueSize=b(e.maxQueueSize,1,100,50),this.transportTimeoutMs=b(e.transportTimeoutMs,250,6e4,5e3),this.destroySignal=new Promise(t=>{this.resolveDestroy=t}),!!this.active){if(!e.project||typeof e.project!="string")throw new Error("project is required");if(!e.transport&&!e.endpoint)throw new Error("endpoint or transport is required");this.endpoint=e.endpoint?this.absoluteUrl(e.endpoint):void 0,window.addEventListener("error",this.onError),window.addEventListener("unhandledrejection",this.onRejection),document.addEventListener("visibilitychange",this.onVisibility),this.networkCaptureEnabled&&X(this),e.captureConsole===!0&&Y(this),this.interval=setInterval(()=>{this.flush()},b(e.flushIntervalMs,10,6e4,1e4))}}captureException(e,t={}){if(!(!this.active||this.destroyed||C(e)))try{if(e!==null&&(typeof e=="object"||typeof e=="function")&&this.seenErrors.has(e))return;let n=N(e),o=B.has(t.type)?t.type:"manual",i=this.makeEvent(o,n.message,{name:n.name,stack:n.stack,componentStack:t.componentStack,context:t.context});this.enqueue(i)&&e!==null&&(typeof e=="object"||typeof e=="function")&&this.seenErrors.add(e)}catch(n){n instanceof k&&this.dropped++}}reportNetwork(e,t,n,o,i){if(!(this.destroyed||!this.active||this.isCollectorUrl(t)||C(i)))try{if(n!==void 0&&!(this.options.shouldCaptureHttp?this.options.shouldCaptureHttp(n,t,e):n>=500))return;let a={method:H(e||"GET",16).toUpperCase(),url:t,status:n,durationMs:o},d=i===void 0?void 0:N(i),l=this.makeEvent(n===void 0?"network":"http",n===void 0?d?.message||"Network request failed":`HTTP ${n}`,{name:d?.name,network:a});this.enqueue(l)}catch{this.dropped++}}captureConsole(e){if(!(!this.active||this.destroyed))try{this.enqueue(this.makeEvent("console",e.map(m).join(" ")))}catch{this.dropped++}}flush(){return!this.active||this.destroyed?Promise.resolve():this.flushing?this.flushing:(this.flushing=this.drain().finally(()=>{this.flushing=void 0}),this.flushing)}destroy(){if(!this.destroyed){this.destroyed=!0,this.interval&&clearInterval(this.interval),this.active&&(window.removeEventListener("error",this.onError),window.removeEventListener("unhandledrejection",this.onRejection),document.removeEventListener("visibilitychange",this.onVisibility),this.networkCaptureEnabled&&D(this),this.options.captureConsole===!0&&W(this)),this.dropped+=this.queue.length+this.inFlight,this.queue.length=0;for(let e of this.cancelWaits)e();for(let e of this.controllers)e.abort();this.resolveDestroy(U)}}getStats(){return{queued:this.queue.length,sent:this.sent,dropped:this.dropped}}absoluteUrl(e){try{return new URL(e,window.location.href).href}catch{return e}}isCollectorUrl(e){if(!this.endpoint)return!1;try{let t=new URL(e,window.location.href),n=new URL(this.endpoint,window.location.href);return t.origin===n.origin&&t.pathname===n.pathname}catch{return e===this.endpoint}}cleanUrl(e){let t=m(e);if(this.options.sanitizeUrl){try{t=this.options.sanitizeUrl(t)}catch{throw new k("URL sanitizer failed")}if(typeof t!="string"||!t)throw new k("URL sanitizer returned no URL")}try{let n=new URL(t,window.location.href);return n.protocol!=="http:"&&n.protocol!=="https:"?"[unsupported URL]":(n.username="",n.password="",n.search="",n.hash="",this.cleanText(n.href,1024,!1))}catch{return this.cleanText(t,1024,!1).split(/[?#]/,1)[0]}}cleanText(e,t,n=!0){let o=m(e);return n&&(o=o.replace(/https?:\/\/[^\s<>"'()[\]]+/gi,i=>this.cleanUrl(i))),o.replace(/\bBearer\s+[A-Za-z0-9._~+\/-]+/gi,"Bearer [REDACTED]").replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/gi,"[REDACTED_EMAIL]").slice(0,t)}cleanContext(e){if(!e||typeof e!="object")return;let t={},n;try{n=Object.keys(e)}catch{return}for(let o of n){if(Object.keys(t).length>=12)break;if(P.test(o))continue;let i=c(e,o),a=this.cleanText(o,80);typeof i=="string"?t[a]=this.cleanText(i,500):(typeof i=="number"&&Number.isFinite(i)||typeof i=="boolean"||i===null)&&(t[a]=i)}return Object.keys(t).length?t:void 0}cleanNetwork(e){if(!e||typeof e!="object")return;let t=c(e,"status"),n=typeof t=="number"&&Number.isInteger(t)&&t>=100&&t<=599?t:void 0;return{method:this.cleanText(c(e,"method")??"GET",16).toUpperCase(),url:this.cleanUrl(c(e,"url")??""),...n===void 0?{}:{status:n},durationMs:b(c(e,"durationMs"),0,36e5,0)}}makeEvent(e,t,n={}){let o=c(navigator,"userAgent"),i=this.cleanContext(n.context),a=this.cleanNetwork(n.network);return{schemaVersion:1,eventId:_(),project:this.cleanText(this.options.project,80),environment:this.cleanText(this.options.environment??"development",80),release:this.cleanText(this.options.release??"unknown",120),sdkVersion:"0.1.0",occurredAt:new Date().toISOString(),viewId:this.viewId,sequence:++this.sequence,elapsedMs:b(w()-this.startedAt,0,36e5,0),type:e,message:this.cleanText(t,1024),...n.name===void 0?{}:{name:this.cleanText(n.name,100)},...n.stack===void 0?{}:{stack:this.cleanText(n.stack,4096)},...n.componentStack===void 0?{}:{componentStack:this.cleanText(n.componentStack,2048)},page:this.cleanUrl(window.location.href),runtime:M.has(this.options.runtime)?this.options.runtime:"browser",...typeof o=="string"?{browser:this.cleanText(o,300)}:{},...i?{context:i}:{},...a?{network:a}:{}}}sanitizeReplacement(e,t){let n=c(e,"type"),o=c(e,"runtime"),i=c(e,"name"),a=c(e,"stack"),d=c(e,"componentStack"),l=c(e,"browser"),u=this.cleanContext(c(e,"context")),p=this.cleanNetwork(c(e,"network"));return{...t,type:B.has(n)?n:t.type,message:this.cleanText(c(e,"message")??t.message,1024),...i===void 0?{name:t.name}:{name:this.cleanText(i,100)},...a===void 0?{stack:t.stack}:{stack:this.cleanText(a,4096)},...d===void 0?{componentStack:t.componentStack}:{componentStack:this.cleanText(d,2048)},page:this.cleanUrl(c(e,"page")??t.page),runtime:M.has(o)?o:t.runtime,...l===void 0?{browser:t.browser}:{browser:this.cleanText(l,300)},...u?{context:u}:{context:void 0},...p?{network:p}:{network:void 0}}}enqueue(e){if(this.destroyed)return!1;let t=e;if(this.options.beforeSend)try{let n={...e,context:e.context&&{...e.context},network:e.network&&{...e.network}},o=this.options.beforeSend(n);if(o===!1||o===null)return!1;t=this.sanitizeReplacement(o===void 0?n:o,e)}catch{return this.dropped++,!1}return S(JSON.stringify(t))>48e3?(this.dropped++,!1):(this.queue.length>=this.maxQueueSize&&(this.queue.shift(),this.dropped++),this.queue.push(t),this.queue.length>=this.maxQueueSize&&this.flush(),!0)}takeBatch(e=20,t=48e3){let n=[],o=S('{"schemaVersion":1,"events":[]}');for(;this.queue.length&&n.length<e;){let i=this.queue[0],a=S(JSON.stringify(i))+(n.length?1:0);if(n.length&&o+a>t)break;if(!n.length&&o+a>t){this.queue.shift(),this.dropped++;continue}n.push(this.queue.shift()),o+=a}return{schemaVersion:1,events:n}}async drain(){for(;!this.destroyed&&this.queue.length;){let e=this.takeBatch();if(e.events.length){this.inFlight+=e.events.length;try{await this.sendWithRetry(e)}finally{this.inFlight-=e.events.length}}}}async sendWithRetry(e){for(let t=0;t<=L.length&&!this.destroyed;t++){let n=new AbortController;this.controllers.add(n);let o,i=new Promise((d,l)=>{o=setTimeout(()=>{n.abort(),l(new Error("Collector transport timed out"))},this.transportTimeoutMs)}),a;try{if(await Promise.race([this.send(e,n.signal),i,this.destroySignal])===U||this.destroyed)return;this.sent+=e.events.length;return}catch(d){if(this.destroyed)return;let l=c(d,"status");if(!(typeof l!="number"||l===429||l>=500)||t===L.length)break;a=L[t]}finally{o&&clearTimeout(o),this.controllers.delete(n)}a!==void 0&&await this.wait(a)}this.destroyed||(this.dropped+=e.events.length)}async send(e,t){if(this.options.transport){await this.options.transport(e,{signal:t});return}let n=await window.fetch(this.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),credentials:"omit",signal:t});if(!n.ok)throw new q(n.status)}wait(e){return new Promise(t=>{let n=()=>{clearTimeout(o),this.cancelWaits.delete(n),t()},o=setTimeout(n,e);this.cancelWaits.add(n)})}tryBeacon(){if(!(this.destroyed||this.options.transport||!this.endpoint||!this.queue.length))try{let e=new URL(this.endpoint);if(e.origin!==window.location.origin||e.search||e.hash||e.username||e.password||typeof navigator.sendBeacon!="function")return;let t=this.queue.slice(0,10);for(;t.length>0;){let o=JSON.stringify({schemaVersion:1,events:t});if(S(o)<=24e3){navigator.sendBeacon(this.endpoint,new Blob([o],{type:"application/json"}))&&this.queue.splice(0,t.length);return}t.pop()}}catch{}}},U=Symbol("destroyed"),T,R;function X(r){T||(T=F()),T.clients.add(r)}function D(r){let e=T;e&&(e.clients.delete(r),e.clients.size||(e.cleanup(),T=void 0))}function V(r,e){let t=typeof Request<"u"&&r instanceof Request?r:void 0;return{url:t?t.url:m(r),method:m(e?.method??t?.method??"GET"),signal:e?.signal??t?.signal}}function F(){let r=new Set,e=window.fetch,t;typeof e=="function"&&(t=function(...u){if(!r.size)return Reflect.apply(e,this,u);let p=w(),f;try{f=V(u[0],u[1])}catch{f={url:"",method:"GET"}}let g;try{g=Reflect.apply(e,this,u)}catch(h){if(!C(h,f.signal))for(let v of r)v.reportNetwork(f.method,f.url,void 0,w()-p,h);throw h}return g.then(h=>{try{let v=h.status;for(let y of r)y.reportNetwork(f.method,f.url,v,w()-p)}catch{}return h},h=>{if(!C(h,f.signal))for(let v of r)v.reportNetwork(f.method,f.url,void 0,w()-p,h);throw h})},window.fetch=t);let n=typeof XMLHttpRequest>"u"?void 0:XMLHttpRequest.prototype,o=n?.open,i=n?.send,a=new WeakMap,d,l;return n&&o&&i&&(d=(function(...u){let p=Reflect.apply(o,this,u);try{a.set(this,{method:m(u[0]),url:m(u[1])})}catch{}return p}),l=function(...u){if(!r.size)return Reflect.apply(i,this,u);let p=a.get(this);if(!p)return Reflect.apply(i,this,u);let f=w(),g=!1,h=!1,v=()=>{g=!0},y=()=>{h=!0},x=()=>{if(this.removeEventListener("abort",v),this.removeEventListener("error",y),this.removeEventListener("timeout",y),this.removeEventListener("loadend",x),!g)try{let E=this.status;if(E===0&&!h)return;for(let I of r)I.reportNetwork(p.method,p.url,E===0?void 0:E,w()-f)}catch{}};try{this.addEventListener("abort",v),this.addEventListener("error",y),this.addEventListener("timeout",y),this.addEventListener("loadend",x)}catch{return Reflect.apply(i,this,u)}try{return Reflect.apply(i,this,u)}catch(E){throw this.removeEventListener("abort",v),this.removeEventListener("error",y),this.removeEventListener("timeout",y),this.removeEventListener("loadend",x),E}},n.open=d,n.send=l),{clients:r,cleanup(){t&&window.fetch===t&&(window.fetch=e),n&&d&&n.open===d&&(n.open=o),n&&l&&n.send===l&&(n.send=i)}}}function Y(r){R||(R=Q()),R.clients.add(r)}function W(r){let e=R;e&&(e.clients.delete(r),e.clients.size||(e.cleanup(),R=void 0))}function Q(){let r=new Set,e=console.error,t=function(...n){try{return Reflect.apply(e,this,n)}finally{for(let o of r)o.captureConsole(n)}};return console.error=t,{clients:r,cleanup(){console.error===t&&(console.error=e)}}}function G(r){return new A(r)}export{G as init};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/index.ts"],
4
+ "sourcesContent": ["import type { ErrorEventRecord, EventBatch, EventType, Runtime } from 'browser-error-log-protocol';\n\nexport type { ErrorEventRecord, EventBatch } from 'browser-error-log-protocol';\n\nexport interface CaptureExtra {\n type?: EventType;\n context?: Record<string, unknown>;\n componentStack?: string;\n}\n\nexport interface TransportContext { signal: AbortSignal }\n\nexport interface BrowserErrorLogOptions {\n project: string;\n environment?: string;\n release?: string;\n endpoint?: string;\n transport?: (batch: EventBatch, context: TransportContext) => void | Promise<void>;\n runtime?: Runtime;\n enabled?: boolean;\n captureConsole?: boolean;\n /** Defaults to true. With a custom transport, automatic network capture requires endpoint for collector exclusion. */\n captureNetwork?: boolean;\n beforeSend?: (event: ErrorEventRecord) => ErrorEventRecord | false | null | void;\n sanitizeUrl?: (url: string) => string;\n shouldCaptureHttp?: (status: number, url: string, method: string) => boolean;\n flushIntervalMs?: number;\n maxQueueSize?: number;\n /** Per-attempt deadline, clamped to 250\u201360000 ms; defaults to 5000 ms. */\n transportTimeoutMs?: number;\n}\n\nexport interface BrowserErrorLogClient {\n captureException(error: unknown, extra?: CaptureExtra): void;\n flush(): Promise<void>;\n destroy(): void;\n getStats(): { queued: number; sent: number; dropped: number };\n}\n\nconst MAX_BATCH_EVENTS = 20;\nconst MAX_BATCH_BYTES = 48_000;\nconst MAX_BEACON_EVENTS = 10;\nconst MAX_BEACON_BYTES = 24_000;\nconst RETRY_DELAYS_MS = [250, 500];\nconst SENSITIVE_KEY = /(?:password|passwd|token|secret|authorization|cookie|session|api.?key|credential|bearer|private.?key)/i;\nconst EVENT_TYPES = new Set<EventType>(['javascript', 'promise', 'react', 'console', 'http', 'network', 'manual']);\nconst RUNTIMES = new Set<Runtime>(['browser', 'webview-ios', 'webview-android', 'unknown']);\nlet fallbackId = 0;\n\nfunction read(object: unknown, key: PropertyKey): unknown {\n try { return object == null ? undefined : Reflect.get(Object(object), key); }\n catch { return undefined; }\n}\n\nfunction safeString(value: unknown): string {\n try { return String(value); }\n catch { return '[unavailable]'; }\n}\n\nfunction trim(value: unknown, length: number): string {\n return safeString(value).slice(0, length);\n}\n\nfunction now(): number {\n try { return performance.now(); }\n catch { return Date.now(); }\n}\n\nfunction newId(): string {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID();\n } catch { /* fall through */ }\n return `${Date.now().toString(36)}-${(++fallbackId).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction isAbort(error: unknown, signal?: AbortSignal | null): boolean {\n try { if (signal?.aborted) return true; }\n catch { /* ignore hostile signal */ }\n return read(error, 'name') === 'AbortError' || read(error, 'code') === 20;\n}\n\nfunction errorFields(error: unknown): { message: string; name?: string; stack?: string } {\n if (error === null || error === undefined) return { message: 'Unknown error' };\n const message = read(error, 'message');\n const name = read(error, 'name');\n const stack = read(error, 'stack');\n return {\n message: message == null ? safeString(error) : safeString(message),\n ...(name == null ? {} : { name: safeString(name) }),\n ...(stack == null ? {} : { stack: safeString(stack) }),\n };\n}\n\nfunction byteLength(value: string): number {\n return new TextEncoder().encode(value).length;\n}\n\nfunction boundedNumber(value: unknown, minimum: number, maximum: number, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value)\n ? Math.min(maximum, Math.max(minimum, Math.floor(value)))\n : fallback;\n}\n\nclass HttpDeliveryError extends Error {\n constructor(readonly status: number) { super(`Collector responded ${status}`); }\n}\n\nclass UrlSanitizationError extends Error {}\n\nclass Client implements BrowserErrorLogClient {\n private readonly active: boolean;\n private readonly endpoint?: string;\n private readonly options: BrowserErrorLogOptions;\n private readonly networkCaptureEnabled: boolean;\n private readonly transportTimeoutMs: number;\n private readonly startedAt = now();\n private readonly viewId = newId();\n private readonly seenErrors = new WeakSet<object>();\n private readonly queue: ErrorEventRecord[] = [];\n private readonly maxQueueSize: number;\n private readonly cancelWaits = new Set<() => void>();\n private readonly controllers = new Set<AbortController>();\n private readonly destroySignal: Promise<symbol>;\n private resolveDestroy!: (value: symbol) => void;\n private interval?: ReturnType<typeof setInterval>;\n private flushing?: Promise<void>;\n private sequence = 0;\n private inFlight = 0;\n private sent = 0;\n private dropped = 0;\n private destroyed = false;\n\n constructor(options: BrowserErrorLogOptions) {\n this.options = options;\n this.active = options.enabled !== false && typeof window !== 'undefined' && typeof document !== 'undefined';\n this.networkCaptureEnabled = options.captureNetwork !== false && (!options.transport || Boolean(options.endpoint));\n this.maxQueueSize = boundedNumber(options.maxQueueSize, 1, 100, 50);\n this.transportTimeoutMs = boundedNumber(options.transportTimeoutMs, 250, 60_000, 5_000);\n this.destroySignal = new Promise(resolve => { this.resolveDestroy = resolve; });\n if (!this.active) return;\n if (!options.project || typeof options.project !== 'string') throw new Error('project is required');\n if (!options.transport && !options.endpoint) throw new Error('endpoint or transport is required');\n this.endpoint = options.endpoint ? this.absoluteUrl(options.endpoint) : undefined;\n window.addEventListener('error', this.onError);\n window.addEventListener('unhandledrejection', this.onRejection);\n document.addEventListener('visibilitychange', this.onVisibility);\n if (this.networkCaptureEnabled) addNetworkClient(this);\n if (options.captureConsole === true) addConsoleClient(this);\n this.interval = setInterval(() => { void this.flush(); }, boundedNumber(options.flushIntervalMs, 10, 60_000, 10_000));\n }\n\n captureException(error: unknown, extra: CaptureExtra = {}): void {\n if (!this.active || this.destroyed || isAbort(error)) return;\n try {\n if (error !== null && (typeof error === 'object' || typeof error === 'function')) {\n if (this.seenErrors.has(error)) return;\n }\n const fields = errorFields(error);\n const type = EVENT_TYPES.has(extra.type as EventType) ? extra.type! : 'manual';\n const event = this.makeEvent(type, fields.message, {\n name: fields.name,\n stack: fields.stack,\n componentStack: extra.componentStack,\n context: extra.context,\n });\n if (this.enqueue(event) && error !== null && (typeof error === 'object' || typeof error === 'function')) {\n this.seenErrors.add(error);\n }\n } catch (error) {\n if (error instanceof UrlSanitizationError) this.dropped++;\n // Diagnostics must never affect the host app.\n }\n }\n\n reportNetwork(method: string, url: string, status: number | undefined, durationMs: number, failure?: unknown): void {\n if (this.destroyed || !this.active || this.isCollectorUrl(url) || isAbort(failure)) return;\n try {\n if (status !== undefined) {\n const include = this.options.shouldCaptureHttp\n ? this.options.shouldCaptureHttp(status, url, method)\n : status >= 500;\n if (!include) return;\n }\n const network = { method: trim(method || 'GET', 16).toUpperCase(), url, status, durationMs };\n const fields = failure === undefined ? undefined : errorFields(failure);\n const event = this.makeEvent(status === undefined ? 'network' : 'http',\n status === undefined ? (fields?.message || 'Network request failed') : `HTTP ${status}`,\n { name: fields?.name, network });\n this.enqueue(event);\n } catch { this.dropped++; /* a failing hook must not expose an unfiltered event */ }\n }\n\n captureConsole(values: unknown[]): void {\n if (!this.active || this.destroyed) return;\n try { this.enqueue(this.makeEvent('console', values.map(safeString).join(' '))); }\n catch { this.dropped++; /* console behavior is never changed by capture */ }\n }\n\n flush(): Promise<void> {\n if (!this.active || this.destroyed) return Promise.resolve();\n if (this.flushing) return this.flushing;\n this.flushing = this.drain().finally(() => { this.flushing = undefined; });\n return this.flushing;\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n if (this.interval) clearInterval(this.interval);\n if (this.active) {\n window.removeEventListener('error', this.onError);\n window.removeEventListener('unhandledrejection', this.onRejection);\n document.removeEventListener('visibilitychange', this.onVisibility);\n if (this.networkCaptureEnabled) removeNetworkClient(this);\n if (this.options.captureConsole === true) removeConsoleClient(this);\n }\n this.dropped += this.queue.length + this.inFlight;\n this.queue.length = 0;\n for (const cancel of this.cancelWaits) cancel();\n for (const controller of this.controllers) controller.abort();\n this.resolveDestroy(DESTROYED);\n }\n\n getStats(): { queued: number; sent: number; dropped: number } {\n return { queued: this.queue.length, sent: this.sent, dropped: this.dropped };\n }\n\n private readonly onError = (event: ErrorEvent): void => {\n this.captureException(event.error ?? event.message ?? 'Script error', { type: 'javascript' });\n };\n\n private readonly onRejection = (event: PromiseRejectionEvent): void => {\n this.captureException(event.reason, { type: 'promise' });\n };\n\n private readonly onVisibility = (): void => {\n if (document.visibilityState === 'hidden') this.tryBeacon();\n };\n\n private absoluteUrl(url: string): string {\n try { return new URL(url, window.location.href).href; }\n catch { return url; }\n }\n\n private isCollectorUrl(url: string): boolean {\n if (!this.endpoint) return false;\n try {\n const request = new URL(url, window.location.href);\n const collector = new URL(this.endpoint, window.location.href);\n return request.origin === collector.origin && request.pathname === collector.pathname;\n } catch { return url === this.endpoint; }\n }\n\n private cleanUrl(input: unknown): string {\n let value = safeString(input);\n if (this.options.sanitizeUrl) {\n try { value = this.options.sanitizeUrl(value); }\n catch { throw new UrlSanitizationError('URL sanitizer failed'); }\n if (typeof value !== 'string' || !value) throw new UrlSanitizationError('URL sanitizer returned no URL');\n }\n try {\n const url = new URL(value, window.location.href);\n if (url.protocol !== 'http:' && url.protocol !== 'https:') return '[unsupported URL]';\n url.username = '';\n url.password = '';\n url.search = '';\n url.hash = '';\n return this.cleanText(url.href, 1024, false);\n } catch { return this.cleanText(value, 1024, false).split(/[?#]/, 1)[0]; }\n }\n\n private cleanText(input: unknown, length: number, replaceUrls = true): string {\n let value = safeString(input);\n if (replaceUrls) {\n value = value.replace(/https?:\\/\\/[^\\s<>\"'()[\\]]+/gi, match => this.cleanUrl(match));\n }\n return value\n .replace(/\\bBearer\\s+[A-Za-z0-9._~+\\/-]+/gi, 'Bearer [REDACTED]')\n .replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}/gi, '[REDACTED_EMAIL]')\n .slice(0, length);\n }\n\n private cleanContext(input: unknown): ErrorEventRecord['context'] {\n if (!input || typeof input !== 'object') return undefined;\n const output: NonNullable<ErrorEventRecord['context']> = {};\n let keys: string[];\n try { keys = Object.keys(input); }\n catch { return undefined; }\n for (const key of keys) {\n if (Object.keys(output).length >= 12) break;\n if (SENSITIVE_KEY.test(key)) continue;\n const value = read(input, key);\n const safeKey = this.cleanText(key, 80);\n if (typeof value === 'string') output[safeKey] = this.cleanText(value, 500);\n else if (typeof value === 'number' && Number.isFinite(value)) output[safeKey] = value;\n else if (typeof value === 'boolean' || value === null) output[safeKey] = value;\n }\n return Object.keys(output).length ? output : undefined;\n }\n\n private cleanNetwork(input: unknown): ErrorEventRecord['network'] {\n if (!input || typeof input !== 'object') return undefined;\n const rawStatus = read(input, 'status');\n const status = typeof rawStatus === 'number' && Number.isInteger(rawStatus) && rawStatus >= 100 && rawStatus <= 599\n ? rawStatus : undefined;\n return {\n method: this.cleanText(read(input, 'method') ?? 'GET', 16).toUpperCase(),\n url: this.cleanUrl(read(input, 'url') ?? ''),\n ...(status === undefined ? {} : { status }),\n durationMs: boundedNumber(read(input, 'durationMs'), 0, 3_600_000, 0),\n };\n }\n\n private makeEvent(type: EventType, message: string, extra: {\n name?: string; stack?: string; componentStack?: string;\n context?: unknown; network?: unknown;\n } = {}): ErrorEventRecord {\n const userAgent = read(navigator, 'userAgent');\n const context = this.cleanContext(extra.context);\n const network = this.cleanNetwork(extra.network);\n return {\n schemaVersion: 1,\n eventId: newId(),\n project: this.cleanText(this.options.project, 80),\n environment: this.cleanText(this.options.environment ?? 'development', 80),\n release: this.cleanText(this.options.release ?? 'unknown', 120),\n sdkVersion: '0.1.0',\n occurredAt: new Date().toISOString(),\n viewId: this.viewId,\n sequence: ++this.sequence,\n elapsedMs: boundedNumber(now() - this.startedAt, 0, 3_600_000, 0),\n type,\n message: this.cleanText(message, 1024),\n ...(extra.name === undefined ? {} : { name: this.cleanText(extra.name, 100) }),\n ...(extra.stack === undefined ? {} : { stack: this.cleanText(extra.stack, 4096) }),\n ...(extra.componentStack === undefined ? {} : { componentStack: this.cleanText(extra.componentStack, 2048) }),\n page: this.cleanUrl(window.location.href),\n runtime: RUNTIMES.has(this.options.runtime as Runtime) ? this.options.runtime! : 'browser',\n ...(typeof userAgent === 'string' ? { browser: this.cleanText(userAgent, 300) } : {}),\n ...(context ? { context } : {}),\n ...(network ? { network } : {}),\n };\n }\n\n private sanitizeReplacement(candidate: unknown, base: ErrorEventRecord): ErrorEventRecord {\n const type = read(candidate, 'type');\n const runtime = read(candidate, 'runtime');\n const name = read(candidate, 'name');\n const stack = read(candidate, 'stack');\n const componentStack = read(candidate, 'componentStack');\n const browser = read(candidate, 'browser');\n const context = this.cleanContext(read(candidate, 'context'));\n const network = this.cleanNetwork(read(candidate, 'network'));\n return {\n ...base,\n type: EVENT_TYPES.has(type as EventType) ? type as EventType : base.type,\n message: this.cleanText(read(candidate, 'message') ?? base.message, 1024),\n ...(name === undefined ? { name: base.name } : { name: this.cleanText(name, 100) }),\n ...(stack === undefined ? { stack: base.stack } : { stack: this.cleanText(stack, 4096) }),\n ...(componentStack === undefined ? { componentStack: base.componentStack } : { componentStack: this.cleanText(componentStack, 2048) }),\n page: this.cleanUrl(read(candidate, 'page') ?? base.page),\n runtime: RUNTIMES.has(runtime as Runtime) ? runtime as Runtime : base.runtime,\n ...(browser === undefined ? { browser: base.browser } : { browser: this.cleanText(browser, 300) }),\n ...(context ? { context } : { context: undefined }),\n ...(network ? { network } : { network: undefined }),\n };\n }\n\n private enqueue(event: ErrorEventRecord): boolean {\n if (this.destroyed) return false;\n let finalEvent = event;\n if (this.options.beforeSend) {\n try {\n const copy = { ...event, context: event.context && { ...event.context }, network: event.network && { ...event.network } };\n const result = this.options.beforeSend(copy);\n if (result === false || result === null) return false;\n finalEvent = this.sanitizeReplacement(result === undefined ? copy : result, event);\n } catch { this.dropped++; return false; }\n }\n // A single event can never make a batch exceed its byte budget.\n if (byteLength(JSON.stringify(finalEvent)) > MAX_BATCH_BYTES) { this.dropped++; return false; }\n if (this.queue.length >= this.maxQueueSize) { this.queue.shift(); this.dropped++; }\n this.queue.push(finalEvent);\n if (this.queue.length >= this.maxQueueSize) void this.flush();\n return true;\n }\n\n private takeBatch(maxEvents = MAX_BATCH_EVENTS, maxBytes = MAX_BATCH_BYTES): EventBatch {\n const events: ErrorEventRecord[] = [];\n let bytes = byteLength('{\"schemaVersion\":1,\"events\":[]}');\n while (this.queue.length && events.length < maxEvents) {\n const next = this.queue[0];\n const size = byteLength(JSON.stringify(next)) + (events.length ? 1 : 0);\n if (events.length && bytes + size > maxBytes) break;\n if (!events.length && bytes + size > maxBytes) { this.queue.shift(); this.dropped++; continue; }\n events.push(this.queue.shift()!);\n bytes += size;\n }\n return { schemaVersion: 1, events };\n }\n\n private async drain(): Promise<void> {\n while (!this.destroyed && this.queue.length) {\n const batch = this.takeBatch();\n if (batch.events.length) {\n this.inFlight += batch.events.length;\n try { await this.sendWithRetry(batch); }\n finally { this.inFlight -= batch.events.length; }\n }\n }\n }\n\n private async sendWithRetry(batch: EventBatch): Promise<void> {\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length && !this.destroyed; attempt++) {\n const controller = new AbortController();\n this.controllers.add(controller);\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_resolve, reject) => {\n timeoutHandle = setTimeout(() => {\n controller.abort();\n reject(new Error('Collector transport timed out'));\n }, this.transportTimeoutMs);\n });\n let retryDelay: number | undefined;\n try {\n const result = await Promise.race([this.send(batch, controller.signal), timeout, this.destroySignal]);\n if (result === DESTROYED || this.destroyed) return;\n this.sent += batch.events.length;\n return;\n } catch (error) {\n if (this.destroyed) return;\n const status = read(error, 'status');\n const retryable = typeof status !== 'number' || status === 429 || status >= 500;\n if (!retryable || attempt === RETRY_DELAYS_MS.length) break;\n retryDelay = RETRY_DELAYS_MS[attempt];\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n this.controllers.delete(controller);\n }\n if (retryDelay !== undefined) await this.wait(retryDelay);\n }\n if (!this.destroyed) this.dropped += batch.events.length;\n }\n\n private async send(batch: EventBatch, signal: AbortSignal): Promise<void> {\n if (this.options.transport) { await this.options.transport(batch, { signal }); return; }\n const response = await window.fetch(this.endpoint!, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(batch),\n credentials: 'omit',\n signal,\n });\n if (!response.ok) throw new HttpDeliveryError(response.status);\n }\n\n private wait(milliseconds: number): Promise<void> {\n return new Promise(resolve => {\n const finish = () => { clearTimeout(timer); this.cancelWaits.delete(finish); resolve(); };\n const timer = setTimeout(finish, milliseconds);\n this.cancelWaits.add(finish);\n });\n }\n\n private tryBeacon(): void {\n if (this.destroyed || this.options.transport || !this.endpoint || !this.queue.length) return;\n try {\n const url = new URL(this.endpoint);\n if (url.origin !== window.location.origin || url.search || url.hash || url.username || url.password) return;\n if (typeof navigator.sendBeacon !== 'function') return;\n const candidates = this.queue.slice(0, MAX_BEACON_EVENTS);\n while (candidates.length > 0) {\n const batch: EventBatch = { schemaVersion: 1, events: candidates };\n const body = JSON.stringify(batch);\n if (byteLength(body) <= MAX_BEACON_BYTES) {\n if (navigator.sendBeacon(this.endpoint, new Blob([body], { type: 'application/json' }))) {\n this.queue.splice(0, candidates.length);\n }\n return;\n }\n candidates.pop();\n }\n } catch { /* best effort only */ }\n }\n}\n\nconst DESTROYED = Symbol('destroyed');\n\ninterface Instrumentation {\n clients: Set<Client>;\n cleanup(): void;\n}\n\nlet networkInstrumentation: Instrumentation | undefined;\nlet consoleInstrumentation: Instrumentation | undefined;\n\nfunction addNetworkClient(client: Client): void {\n if (!networkInstrumentation) networkInstrumentation = installNetwork();\n networkInstrumentation.clients.add(client);\n}\n\nfunction removeNetworkClient(client: Client): void {\n const instrumentation = networkInstrumentation;\n if (!instrumentation) return;\n instrumentation.clients.delete(client);\n if (!instrumentation.clients.size) {\n instrumentation.cleanup();\n networkInstrumentation = undefined;\n }\n}\n\nfunction describeFetch(input: RequestInfo | URL, init?: RequestInit): { url: string; method: string; signal?: AbortSignal | null } {\n const request = typeof Request !== 'undefined' && input instanceof Request ? input : undefined;\n const url = request ? request.url : safeString(input);\n return { url, method: safeString(init?.method ?? request?.method ?? 'GET'), signal: init?.signal ?? request?.signal };\n}\n\nfunction installNetwork(): Instrumentation {\n const clients = new Set<Client>();\n const originalFetch = window.fetch;\n let wrappedFetch: typeof fetch | undefined;\n if (typeof originalFetch === 'function') {\n wrappedFetch = function (this: typeof window, ...args: Parameters<typeof fetch>): ReturnType<typeof fetch> {\n if (!clients.size) return Reflect.apply(originalFetch, this, args);\n const started = now();\n let request: ReturnType<typeof describeFetch>;\n try { request = describeFetch(args[0], args[1]); }\n catch { request = { url: '', method: 'GET' }; }\n let promise: ReturnType<typeof fetch>;\n try { promise = Reflect.apply(originalFetch, this, args); }\n catch (error) {\n if (!isAbort(error, request.signal)) for (const client of clients) client.reportNetwork(request.method, request.url, undefined, now() - started, error);\n throw error;\n }\n return promise.then(\n response => {\n try {\n const status = response.status;\n for (const client of clients) client.reportNetwork(request.method, request.url, status, now() - started);\n } catch { /* telemetry cannot change the fetch result */ }\n return response;\n },\n error => {\n if (!isAbort(error, request.signal)) for (const client of clients) client.reportNetwork(request.method, request.url, undefined, now() - started, error);\n throw error;\n },\n );\n };\n window.fetch = wrappedFetch;\n }\n\n const prototype = typeof XMLHttpRequest === 'undefined' ? undefined : XMLHttpRequest.prototype;\n const originalOpen = prototype?.open;\n const originalSend = prototype?.send;\n const metadata = new WeakMap<XMLHttpRequest, { method: string; url: string }>();\n let wrappedOpen: typeof XMLHttpRequest.prototype.open | undefined;\n let wrappedSend: typeof XMLHttpRequest.prototype.send | undefined;\n if (prototype && originalOpen && originalSend) {\n wrappedOpen = (function (this: XMLHttpRequest, ...args: unknown[]): void {\n const result = Reflect.apply(originalOpen, this, args);\n try { metadata.set(this, { method: safeString(args[0]), url: safeString(args[1]) }); }\n catch { /* native open already succeeded */ }\n return result;\n }) as typeof XMLHttpRequest.prototype.open;\n wrappedSend = function (this: XMLHttpRequest, ...args: Parameters<XMLHttpRequest['send']>): void {\n if (!clients.size) return Reflect.apply(originalSend, this, args);\n const details = metadata.get(this);\n if (!details) return Reflect.apply(originalSend, this, args);\n const started = now();\n let aborted = false;\n let failed = false;\n const onAbort = () => { aborted = true; };\n const onFailure = () => { failed = true; };\n const onLoadEnd = () => {\n this.removeEventListener('abort', onAbort);\n this.removeEventListener('error', onFailure);\n this.removeEventListener('timeout', onFailure);\n this.removeEventListener('loadend', onLoadEnd);\n if (aborted) return;\n try {\n const status = this.status;\n if (status === 0 && !failed) return;\n for (const client of clients) client.reportNetwork(details.method, details.url,\n status === 0 ? undefined : status, now() - started);\n } catch { /* XHR state may be unavailable */ }\n };\n try {\n this.addEventListener('abort', onAbort);\n this.addEventListener('error', onFailure);\n this.addEventListener('timeout', onFailure);\n this.addEventListener('loadend', onLoadEnd);\n } catch { return Reflect.apply(originalSend, this, args); }\n try { return Reflect.apply(originalSend, this, args); }\n catch (error) {\n this.removeEventListener('abort', onAbort);\n this.removeEventListener('error', onFailure);\n this.removeEventListener('timeout', onFailure);\n this.removeEventListener('loadend', onLoadEnd);\n throw error;\n }\n };\n prototype.open = wrappedOpen!;\n prototype.send = wrappedSend;\n }\n return {\n clients,\n cleanup() {\n if (wrappedFetch && window.fetch === wrappedFetch) window.fetch = originalFetch;\n if (prototype && wrappedOpen && prototype.open === wrappedOpen) prototype.open = originalOpen!;\n if (prototype && wrappedSend && prototype.send === wrappedSend) prototype.send = originalSend!;\n },\n };\n}\n\nfunction addConsoleClient(client: Client): void {\n if (!consoleInstrumentation) consoleInstrumentation = installConsole();\n consoleInstrumentation.clients.add(client);\n}\n\nfunction removeConsoleClient(client: Client): void {\n const instrumentation = consoleInstrumentation;\n if (!instrumentation) return;\n instrumentation.clients.delete(client);\n if (!instrumentation.clients.size) {\n instrumentation.cleanup();\n consoleInstrumentation = undefined;\n }\n}\n\nfunction installConsole(): Instrumentation {\n const clients = new Set<Client>();\n const original = console.error;\n const wrapped: typeof console.error = function (this: Console, ...values: unknown[]): void {\n try { return Reflect.apply(original, this, values); }\n finally { for (const client of clients) client.captureConsole(values); }\n };\n console.error = wrapped;\n return { clients, cleanup() { if (console.error === wrapped) console.error = original; } };\n}\n\nexport function init(options: BrowserErrorLogOptions): BrowserErrorLogClient {\n return new Client(options);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["RETRY_DELAYS_MS", "SENSITIVE_KEY", "EVENT_TYPES", "RUNTIMES", "fallbackId", "read", "object", "key", "safeString", "value", "trim", "length", "now", "newId", "isAbort", "error", "signal", "errorFields", "message", "name", "stack", "byteLength", "boundedNumber", "minimum", "maximum", "fallback", "HttpDeliveryError", "status", "__publicField", "UrlSanitizationError", "Client", "options", "event", "resolve", "addNetworkClient", "addConsoleClient", "extra", "fields", "type", "method", "url", "durationMs", "failure", "network", "values", "removeNetworkClient", "removeConsoleClient", "cancel", "controller", "DESTROYED", "request", "collector", "input", "replaceUrls", "match", "output", "keys", "safeKey", "rawStatus", "userAgent", "context", "candidate", "base", "runtime", "componentStack", "browser", "finalEvent", "copy", "result", "maxEvents", "maxBytes", "events", "bytes", "next", "size", "batch", "attempt", "timeoutHandle", "timeout", "_resolve", "reject", "retryDelay", "response", "milliseconds", "finish", "timer", "candidates", "body", "networkInstrumentation", "consoleInstrumentation", "client", "installNetwork", "instrumentation", "describeFetch", "init", "clients", "originalFetch", "wrappedFetch", "args", "started", "promise", "prototype", "originalOpen", "originalSend", "metadata", "wrappedOpen", "wrappedSend", "details", "aborted", "failed", "onAbort", "onFailure", "onLoadEnd", "installConsole", "original", "wrapped"]
7
+ }
package/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "browser-error-log",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "A small, framework-independent browser error SDK for a collector you control.",
5
+ "keywords": [
6
+ "browser",
7
+ "error-monitoring",
8
+ "self-hosted",
9
+ "typescript",
10
+ "telemetry"
11
+ ],
12
+ "license": "MIT",
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "registry": "https://registry.npmjs.org/"
16
+ },
17
+ "type": "module",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "require": "./dist/index.cjs"
23
+ }
24
+ },
25
+ "dependencies": {
26
+ "browser-error-log-protocol": "0.1.0"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "README.md",
31
+ "LICENSE"
32
+ ],
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/hyeonse-swing/browser-error-log.git",
36
+ "directory": "packages/browser"
37
+ },
38
+ "homepage": "https://github.com/hyeonse-swing/browser-error-log#readme",
39
+ "bugs": {
40
+ "url": "https://github.com/hyeonse-swing/browser-error-log/issues"
41
+ }
42
+ }