@accelerup-llc/web-monitor 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 AccelerUp
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 ADDED
@@ -0,0 +1,137 @@
1
+ # @accelerup-llc/web-monitor
2
+
3
+ Lightweight, zero-dependency error & warning monitoring for Next.js. Initialize
4
+ **once**, and every uncaught error, unhandled promise rejection, `console.error`
5
+ and `console.warn` from your users is batched and shipped to AccelerUp. Works
6
+ with **both the App Router and the Pages Router** in the same codebase.
7
+
8
+ - **Zero runtime dependencies** — a few KB gzipped, `react` is an optional peer.
9
+ - **Errors & warnings only** — nothing else is captured. No `console.log`, no analytics, no tracking.
10
+ - **Single init, idempotent** — safe across HMR, double imports, and both routers mounting.
11
+ - **Never breaks your app** — every capture path is wrapped; failures are swallowed.
12
+ - **Resilient transport** — batched, deduped, rate-limited, `sendBeacon` on page hide, retry with backoff.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ npm install @accelerup-llc/web-monitor
18
+ ```
19
+
20
+ ## Setup — one place, both routers
21
+
22
+ **1. Add two env vars** (`.env`):
23
+
24
+ ```bash
25
+ NEXT_PUBLIC_ACCELERUP_INGEST_URL=https://api.accelerup.com/ingest/web-errors
26
+ NEXT_PUBLIC_ACCELERUP_KEY=wm_your_public_ingest_key
27
+ ```
28
+
29
+ The key is **public and write-only** — it only grants "submit an error event",
30
+ so it is safe to expose in the browser bundle.
31
+
32
+ **2. Init once.** Next.js 13.4+ runs `instrumentation-client.ts` (project root,
33
+ or `src/`) on the client before anything else, for **both** routers — the single
34
+ init point:
35
+
36
+ ```ts
37
+ // instrumentation-client.ts
38
+ import { init } from '@accelerup-llc/web-monitor';
39
+
40
+ init({
41
+ ingestUrl: process.env.NEXT_PUBLIC_ACCELERUP_INGEST_URL!,
42
+ key: process.env.NEXT_PUBLIC_ACCELERUP_KEY!,
43
+ release: process.env.NEXT_PUBLIC_APP_VERSION,
44
+ environment: process.env.NODE_ENV,
45
+ });
46
+ ```
47
+
48
+ That's it. No other code changes anywhere in your app.
49
+
50
+ > Prefer a single DSN string? `init({ dsn: 'https://KEY@host/PROJECT_ID' })` also works.
51
+
52
+ <details>
53
+ <summary>Older Next.js without instrumentation-client?</summary>
54
+
55
+ **App Router** — a tiny client component imported in the root layout:
56
+
57
+ ```tsx
58
+ // app/monitor.tsx
59
+ 'use client';
60
+ import { useEffect } from 'react';
61
+ import { init } from '@accelerup-llc/web-monitor';
62
+ export function Monitor() {
63
+ useEffect(() => { init({ dsn: process.env.NEXT_PUBLIC_ACCELERUP_DSN! }); }, []);
64
+ return null;
65
+ }
66
+ ```
67
+ ```tsx
68
+ // app/layout.tsx
69
+ import { Monitor } from './monitor';
70
+ export default function RootLayout({ children }) {
71
+ return <html><body><Monitor />{children}</body></html>;
72
+ }
73
+ ```
74
+
75
+ **Pages Router** — in `_app.tsx`:
76
+
77
+ ```tsx
78
+ // pages/_app.tsx
79
+ import { init } from '@accelerup-llc/web-monitor';
80
+ if (typeof window !== 'undefined') init({ dsn: process.env.NEXT_PUBLIC_ACCELERUP_DSN! });
81
+ ```
82
+ </details>
83
+
84
+ ## Optional: React error boundary
85
+
86
+ Catches render-time crashes that global handlers can't see.
87
+
88
+ ```tsx
89
+ import { ErrorBoundary } from '@accelerup-llc/web-monitor/react';
90
+
91
+ <ErrorBoundary fallback={<p>Something went wrong.</p>}>
92
+ <YourApp />
93
+ </ErrorBoundary>
94
+ ```
95
+
96
+ ## Optional: manual reporting
97
+
98
+ ```ts
99
+ import { captureError, captureMessage, setUser } from '@accelerup-llc/web-monitor';
100
+
101
+ try { risky(); } catch (e) { captureError(e); }
102
+ captureMessage('Payment retried', 'warning');
103
+ setUser({ id: 'user_123' }); // anonymous id only — no PII required
104
+ ```
105
+
106
+ ## Configuration
107
+
108
+ | Option | Default | Description |
109
+ | --- | --- | --- |
110
+ | `ingestUrl` + `key` | — | **Required** (or `dsn`). Endpoint URL + public ingest key. |
111
+ | `project` | — | Optional app id, sent as a tag. |
112
+ | `dsn` | — | Alternative to `ingestUrl`+`key`: `https://KEY@host/PROJECT_ID`. |
113
+ | `endpoint` | derived | Override the full ingest URL (with `dsn`). |
114
+ | `release` / `environment` | — | Group issues per release/env. |
115
+ | `enabled` | `true` | Set `false` to disable entirely. |
116
+ | `captureError` | `true` | Uncaught `window` errors. |
117
+ | `captureUnhandledRejection` | `true` | Unhandled promise rejections. |
118
+ | `captureConsole` | `true` | `console.error`/`warn`. Or `{ error, warn }`. |
119
+ | `ignoreErrors` | — | `(string \| RegExp)[]` to drop by message. |
120
+ | `denyUrls` / `allowUrls` | — | Filter by stack/url. |
121
+ | `sampleRate` / `warningSampleRate` | `1` | `0..1` sampling. |
122
+ | `maxEventsPerMinute` | `30` | Token-bucket flood guard. |
123
+ | `dedupeWindow` | `5000` | ms window to suppress duplicates. |
124
+ | `flushInterval` / `maxBatchSize` | `5000` / `20` | Batching. |
125
+ | `maxQueueSize` | `100` | In-memory buffer cap. |
126
+ | `beforeSend` | — | `(event) => event \| null` last-chance hook. |
127
+ | `debug` | `false` | Verbose internal logging. |
128
+
129
+ ## Privacy
130
+
131
+ URLs are reduced to `origin + pathname` (query & hash stripped) to avoid leaking
132
+ tokens/PII. Only error/warning content is collected. Use `beforeSend` to redact
133
+ further.
134
+
135
+ ## License
136
+
137
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,6 @@
1
+ 'use strict';function b(t,e){let n=[];if(t.captureError!==false){let i=s=>{try{let o=s.target;if(o&&o!==window&&o.nodeName)return;let a=s.error;e({level:"error",source:"onerror",message:s.message||a&&a.message||"Unknown error",stack:a&&a.stack,type:a&&a.name,filename:s.filename,lineno:s.lineno,colno:s.colno});}catch{}};window.addEventListener("error",i,true),n.push(()=>window.removeEventListener("error",i,true));}if(t.captureUnhandledRejection!==false){let i=s=>{try{let o=s.reason,a="Unhandled Promise Rejection",u,E;o instanceof Error?(a=`${a}: ${o.message}`,u=o.stack,E=o.name):typeof o=="string"?a=`${a}: ${o}`:o!=null&&(a=`${a}: ${k(o)}`),e({level:"error",source:"unhandledrejection",message:a,stack:u,type:E});}catch{}};window.addEventListener("unhandledrejection",i),n.push(()=>window.removeEventListener("unhandledrejection",i));}let r=I(t.captureConsole);return ["error","warn"].forEach(i=>{if(!r[i])return;let s=console[i],o=i==="warn"?"warning":"error";console[i]=function(...u){s.apply(console,u);try{e(j(o,u));}catch{}},n.push(()=>{console[i]=s;});}),()=>n.forEach(i=>{try{i();}catch{}})}function I(t){return t===false?{error:false,warn:false}:t===void 0||t===true?{error:true,warn:true}:{error:t.error!==false,warn:t.warn!==false}}function j(t,e){let n,r,i=e.find(o=>o instanceof Error);i&&(n=i.stack,r=i.name);let s=e.map(z).join(" ").slice(0,2e3)||(t==="warning"?"console.warn":"console.error");return {level:t,source:"console",message:s,stack:n,type:r}}function z(t){return typeof t=="string"?t:t instanceof Error?t.message:k(t)}function k(t){try{return typeof t=="object"&&t!==null?JSON.stringify(t):String(t)}catch{return Object.prototype.toString.call(t)}}var p=class{constructor(e){this.windowMs=e;this.seen=new Map;}shouldSend(e,n){let r=this.seen.get(e);if(r!==void 0&&n-r<this.windowMs)return false;if(this.seen.set(e,n),this.seen.size>200)for(let[i,s]of this.seen)n-s>this.windowMs&&this.seen.delete(i);return true}},h=class{constructor(e){this.maxPerMin=e;this.tokens=e,this.last=Date.now();}allow(e){let n=e-this.last;return this.last=e,this.tokens=Math.min(this.maxPerMin,this.tokens+n/6e4*this.maxPerMin),this.tokens>=1?(this.tokens-=1,true):false}};var f="0.1.0";var m=class{constructor(e,n){this.dsn=e;this.opts=n;this.queue=[];this.timer=null;this.sending=false;this.failures=0;let r=e.ingestUrl.indexOf("?")===-1?"?":"&";this.url=`${e.ingestUrl}${r}key=${encodeURIComponent(e.publicKey)}&project=${encodeURIComponent(e.projectId)}`;}add(e){this.queue.length>=this.opts.maxQueueSize&&this.queue.shift(),this.queue.push(e),this.queue.length>=this.opts.maxBatchSize?this.flush():this.schedule();}schedule(){this.timer==null&&(this.timer=setTimeout(()=>{this.timer=null,this.flush();},this.opts.flushInterval));}flush(e=false){if(this.timer!=null&&(clearTimeout(this.timer),this.timer=null),this.queue.length===0||this.sending&&!e)return;let n=this.queue.splice(0,this.opts.maxBatchSize),r=JSON.stringify(this.envelope(n));if(e&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){try{navigator.sendBeacon(this.url,new Blob([r],{type:"text/plain;charset=UTF-8"}))||this.queue.unshift(...n);}catch{this.queue.unshift(...n);}return}typeof fetch=="function"&&(this.sending=true,fetch(this.url,{method:"POST",body:r,keepalive:true,mode:"cors",credentials:"omit"}).then(i=>{this.sending=false,i.status>=500?this.requeue(n):this.failures=0;}).catch(()=>{this.sending=false,this.requeue(n);}));}requeue(e){if(this.failures++,this.failures>5){this.failures=0;return}let n=this.opts.maxQueueSize-this.queue.length;n>0&&this.queue.unshift(...e.slice(-n));let r=Math.min(3e4,1e3*Math.pow(2,this.failures));setTimeout(()=>this.flush(),r);}envelope(e){return {sdk:{name:"@accelerup-llc/web-monitor",version:f},project_id:this.dsn.projectId,sent_at:Date.now(),events:e}}};function P(t,e=0){let n=3735928559^e,r=1103547991^e;for(let i=0;i<t.length;i++){let s=t.charCodeAt(i);n=Math.imul(n^s,2654435761),r=Math.imul(r^s,1597334677);}return n=Math.imul(n^n>>>16,2246822507)^Math.imul(r^r>>>13,3266489909),r=Math.imul(r^r>>>16,2246822507)^Math.imul(n^n>>>13,3266489909),(4294967296*(2097151&r)+(n>>>0)).toString(16).padStart(13,"0")}function M(t,e=3){return t?t.split(`
2
+ `).slice(0,e+1).join(`
3
+ `):""}function S(t){let e=t.filter(Boolean).join(`
4
+ `).replace(/:\d+:\d+/g,"").replace(/0x[0-9a-fA-F]+/g,"0x").replace(/\b\d{4,}\b/g,"N").replace(/https?:\/\/[^\s)]+/g,n=>{try{let r=new URL(n);return r.origin+r.pathname}catch{return n}});return P(e)}function C(t){if(!t)return "";try{let e=new URL(t);return e.origin+e.pathname}catch{return t.split("?")[0].split("#")[0]}}var x=null;function y(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return (t==="x"?e:e&3|8).toString(16)})}function R(){return x||(x=y()),x}var g="__ACCELERUP_WEB_MONITOR__";function w(t){return typeof console<"u"&&typeof console[t]=="function"?console[t].bind(console):()=>{}}var l={log:w("log"),warn:w("warn"),error:w("error")};function d(){return typeof window<"u"&&typeof document<"u"}var v=class{constructor(e,n){this.config=e;this.dsn=n;this.inCapture=false;this.transport=new m(n,{flushInterval:e.flushInterval,maxBatchSize:e.maxBatchSize,maxQueueSize:e.maxQueueSize}),this.dedupe=new p(e.dedupeWindow),this.rate=new h(e.maxEventsPerMinute);}start(){this.uninstall||(this.uninstall=b(this.config,e=>this.capture(e)),this.installLifecycle(),this.config.debug&&l.log("[accelerup] monitor started",{release:this.config.release}));}capture(e){if(!this.inCapture){this.inCapture=true;try{if(!e.message||e.stack&&e.stack.indexOf(this.dsn.ingestUrl)!==-1||this.isIgnored(e.message))return;let n=C(typeof location<"u"?location.href:"");if(!this.passUrlFilters(e.stack,n))return;let r=e.level==="warning"?this.config.warningSampleRate:this.config.sampleRate;if(r<1&&Math.random()>r)return;let i=e.stack?e.stack.slice(0,this.config.maxStackChars):void 0,s=S([e.type,e.message,M(i)]),o=Date.now();if(!this.dedupe.shouldSend(s,o)||!this.rate.allow(o))return;let a={event_id:y(),level:e.level,message:e.message.slice(0,2e3),type:e.type,stack:i,source:e.source,fingerprint:s,url:n,filename:e.filename,lineno:e.lineno,colno:e.colno,release:this.config.release,environment:this.config.environment,session_id:R(),user:this.config.user,user_agent:typeof navigator<"u"?navigator.userAgent:"",timestamp:o,tags:this.config.tags},u=a;if(this.config.beforeSend)try{u=this.config.beforeSend(a);}catch{u=a;}if(!u)return;this.transport.add(u),this.config.debug&&l.log("[accelerup] captured",u.level,u.message);}catch{}finally{this.inCapture=false;}}}captureException(e,n){let r="Error",i,s;if(e instanceof Error)r=e.message,i=e.stack,s=e.name;else if(typeof e=="string")r=e;else if(e!=null)try{r=JSON.stringify(e);}catch{r=String(e);}this.capture({level:n?.level??"error",source:n?.source??"manual",message:r,stack:i,type:s});}captureMessage(e,n="warning"){this.capture({level:n,source:"manual",message:e});}setUser(e){this.config.user=e;}flush(){this.transport.flush();}close(){this.transport.flush(true),this.uninstall&&(this.uninstall(),this.uninstall=void 0);}isIgnored(e){let n=this.config.ignoreErrors;return n?n.some(r=>typeof r=="string"?e.indexOf(r)!==-1:r.test(e)):false}passUrlFilters(e,n){let r=`${e||""} ${n}`,{denyUrls:i,allowUrls:s}=this.config;return !(i&&i.some(o=>U(o,r))||s&&s.length>0&&!s.some(o=>U(o,r)))}installLifecycle(){if(!d())return;let e=()=>this.transport.flush(true);window.addEventListener("pagehide",e),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.transport.flush(true);});}};function U(t,e){return typeof t=="string"?e.indexOf(t)!==-1:t.test(e)}function L(t){return t.ingestUrl&&t.key?{publicKey:t.key,projectId:t.project||"",ingestUrl:t.ingestUrl.replace(/\/+$/,"")}:t.dsn?_(t.dsn,t.endpoint):null}function _(t,e){try{let n=new URL(t),r=n.username||n.searchParams.get("key")||"",i=n.pathname.replace(/^\/+/,"").split("/")[0]||n.searchParams.get("project")||"";if(!r||!i)return null;let s=e?e.replace(/\/+$/,""):`${n.protocol}//${n.host}/ingest/web-errors`;return {publicKey:r,projectId:i,ingestUrl:s}}catch{return null}}function O(t){if(!d()||t.enabled===false)return;if(!t||!t.dsn&&!(t.ingestUrl&&t.key)){l.warn("[accelerup] init() needs either { ingestUrl, key } or { dsn } \u2014 skipping.");return}let e=window,n=e[g];if(n&&n.__initialized&&n.client)return n.client;let r=L(t);if(!r){l.warn("[accelerup] invalid config \u2014 provide { ingestUrl, key } or a valid dsn");return}let i=new v(B(t),r);return e[g]={__initialized:true,client:i,version:f},i.start(),i}function c(){return d()?window[g]?.client:void 0}function B(t){return {...t,sampleRate:t.sampleRate??1,warningSampleRate:t.warningSampleRate??1,maxStackChars:t.maxStackChars??4e3,dedupeWindow:t.dedupeWindow??5e3,maxEventsPerMinute:t.maxEventsPerMinute??30,flushInterval:t.flushInterval??5e3,maxBatchSize:t.maxBatchSize??20,maxQueueSize:t.maxQueueSize??100}}function $(t,e){c()?.captureException(t,e);}function q(t,e="warning"){c()?.captureMessage(t,e);}function D(t){c()?.setUser(t);}function N(){c()?.flush();}
5
+ exports.VERSION=f;exports.captureError=$;exports.captureMessage=q;exports.flush=N;exports.getClient=c;exports.init=O;exports.setUser=D;//# sourceMappingURL=index.cjs.map
6
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/handlers.ts","../src/core/dedup.ts","../src/version.ts","../src/transport/transport.ts","../src/core/fingerprint.ts","../src/core/scrub.ts","../src/core/session.ts","../src/utils.ts","../src/core/client.ts","../src/dsn.ts","../src/init.ts","../src/capture.ts"],"names":["installHandlers","config","capture","cleanups","onError","event","target","err","onRejection","reason","message","stack","type","safeStringify","consoleCfg","resolveConsole","method","orig","level","args","consoleEvent","c","opt","errArg","a","formatArg","arg","value","Dedupe","windowMs","fingerprint","now","last","k","t","RateLimiter","maxPerMin","elapsed","VERSION","Transport","dsn","opts","sep","useBeacon","batch","body","res","room","delay","events","cyrb53","str","seed","h1","h2","ch","topFrames","n","makeFingerprint","parts","normalized","m","u","scrubUrl","url","sessionId","uuid","r","getSessionId","GLOBAL_KEY","bind","originalConsole","isBrowser","Monitor","raw","rate","final","error","user","list","p","hay","denyUrls","allowUrls","match","beacon","resolveEndpoint","parseDsn","endpointOverride","publicKey","projectId","ingestUrl","init","w","existing","client","resolveConfig","getClient","captureError","captureMessage","setUser","flush"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { EventSource, Level, MonitorConfig } from '../types';\n\n/** A partial event produced by a capture source, before enrichment. */\nexport interface RawEvent {\n level: Level;\n source: EventSource;\n message: string;\n stack?: string;\n type?: string;\n filename?: string;\n lineno?: number;\n colno?: number;\n}\n\ntype CaptureFn = (raw: RawEvent) => void;\n\n/**\n * Installs the global capture sources. Returns an uninstall function that\n * restores everything (used by Monitor.close and for HMR safety).\n */\nexport function installHandlers(config: MonitorConfig, capture: CaptureFn): () => void {\n const cleanups: Array<() => void> = [];\n\n if (config.captureError !== false) {\n const onError = (event: ErrorEvent) => {\n try {\n const target = event.target as (Node & { nodeName?: string }) | null;\n // Resource-load errors (img/script 404) fire on the element, not window.\n if (target && target !== (window as unknown as EventTarget) && target.nodeName) return;\n const err = event.error as Error | undefined;\n capture({\n level: 'error',\n source: 'onerror',\n message: event.message || (err && err.message) || 'Unknown error',\n stack: err && err.stack,\n type: err && err.name,\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n });\n } catch {\n /* never throw from a global handler */\n }\n };\n window.addEventListener('error', onError, true);\n cleanups.push(() => window.removeEventListener('error', onError, true));\n }\n\n if (config.captureUnhandledRejection !== false) {\n const onRejection = (event: PromiseRejectionEvent) => {\n try {\n const reason = event.reason as unknown;\n let message = 'Unhandled Promise Rejection';\n let stack: string | undefined;\n let type: string | undefined;\n if (reason instanceof Error) {\n message = `${message}: ${reason.message}`;\n stack = reason.stack;\n type = reason.name;\n } else if (typeof reason === 'string') {\n message = `${message}: ${reason}`;\n } else if (reason != null) {\n message = `${message}: ${safeStringify(reason)}`;\n }\n capture({ level: 'error', source: 'unhandledrejection', message, stack, type });\n } catch {\n /* noop */\n }\n };\n window.addEventListener('unhandledrejection', onRejection);\n cleanups.push(() => window.removeEventListener('unhandledrejection', onRejection));\n }\n\n const consoleCfg = resolveConsole(config.captureConsole);\n (['error', 'warn'] as const).forEach((method) => {\n if (!consoleCfg[method]) return;\n const orig = console[method];\n const level: Level = method === 'warn' ? 'warning' : 'error';\n console[method] = function patched(...args: unknown[]): void {\n orig.apply(console, args as []);\n try {\n capture(consoleEvent(level, args));\n } catch {\n /* noop */\n }\n };\n cleanups.push(() => {\n console[method] = orig;\n });\n });\n\n return () =>\n cleanups.forEach((c) => {\n try {\n c();\n } catch {\n /* noop */\n }\n });\n}\n\nfunction resolveConsole(opt: MonitorConfig['captureConsole']): { error: boolean; warn: boolean } {\n if (opt === false) return { error: false, warn: false };\n if (opt === undefined || opt === true) return { error: true, warn: true };\n return { error: opt.error !== false, warn: opt.warn !== false };\n}\n\nfunction consoleEvent(level: Level, args: unknown[]): RawEvent {\n let stack: string | undefined;\n let type: string | undefined;\n const errArg = args.find((a) => a instanceof Error) as Error | undefined;\n if (errArg) {\n stack = errArg.stack;\n type = errArg.name;\n }\n const message =\n args.map(formatArg).join(' ').slice(0, 2000) ||\n (level === 'warning' ? 'console.warn' : 'console.error');\n return { level, source: 'console', message, stack, type };\n}\n\nfunction formatArg(arg: unknown): string {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n return safeStringify(arg);\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n if (typeof value === 'object' && value !== null) return JSON.stringify(value);\n return String(value);\n } catch {\n return Object.prototype.toString.call(value);\n }\n}\n","/** Suppresses identical events seen within a sliding time window. */\nexport class Dedupe {\n private seen = new Map<string, number>();\n\n constructor(private windowMs: number) {}\n\n shouldSend(fingerprint: string, now: number): boolean {\n const last = this.seen.get(fingerprint);\n if (last !== undefined && now - last < this.windowMs) return false;\n\n this.seen.set(fingerprint, now);\n\n if (this.seen.size > 200) {\n for (const [k, t] of this.seen) {\n if (now - t > this.windowMs) this.seen.delete(k);\n }\n }\n return true;\n }\n}\n\n/** Token-bucket limiter so a misbehaving page can't flood the backend. */\nexport class RateLimiter {\n private tokens: number;\n private last: number;\n\n constructor(private maxPerMin: number) {\n this.tokens = maxPerMin;\n this.last = Date.now();\n }\n\n allow(now: number): boolean {\n const elapsed = now - this.last;\n this.last = now;\n this.tokens = Math.min(this.maxPerMin, this.tokens + (elapsed / 60000) * this.maxPerMin);\n if (this.tokens >= 1) {\n this.tokens -= 1;\n return true;\n }\n return false;\n }\n}\n","export const VERSION = '0.1.0';\n","import type { MonitoredEvent } from '../types';\nimport type { ParsedDsn } from '../dsn';\nimport { VERSION } from '../version';\n\ninterface TransportOpts {\n flushInterval: number;\n maxBatchSize: number;\n maxQueueSize: number;\n}\n\n/**\n * Buffers events and ships them in batches. Uses fetch(keepalive) while the\n * page is alive and navigator.sendBeacon on page hide so the last batch is\n * never lost. Failed batches are retried with capped exponential backoff.\n */\nexport class Transport {\n private queue: MonitoredEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private sending = false;\n private failures = 0;\n private readonly url: string;\n\n constructor(private dsn: ParsedDsn, private opts: TransportOpts) {\n const sep = dsn.ingestUrl.indexOf('?') === -1 ? '?' : '&';\n // Auth via query params (not headers) and a default text/plain body keep\n // this a CORS \"simple request\" — no preflight OPTIONS round-trip, and\n // sendBeacon (which can't set headers) uses the same URL.\n this.url =\n `${dsn.ingestUrl}${sep}key=${encodeURIComponent(dsn.publicKey)}` +\n `&project=${encodeURIComponent(dsn.projectId)}`;\n }\n\n add(event: MonitoredEvent): void {\n if (this.queue.length >= this.opts.maxQueueSize) this.queue.shift();\n this.queue.push(event);\n if (this.queue.length >= this.opts.maxBatchSize) this.flush();\n else this.schedule();\n }\n\n private schedule(): void {\n if (this.timer != null) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n this.flush();\n }, this.opts.flushInterval);\n }\n\n flush(useBeacon = false): void {\n if (this.timer != null) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.queue.length === 0) return;\n if (this.sending && !useBeacon) return;\n\n const batch = this.queue.splice(0, this.opts.maxBatchSize);\n const body = JSON.stringify(this.envelope(batch));\n\n if (useBeacon && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n try {\n const ok = navigator.sendBeacon(this.url, new Blob([body], { type: 'text/plain;charset=UTF-8' }));\n if (!ok) this.queue.unshift(...batch);\n } catch {\n this.queue.unshift(...batch);\n }\n return;\n }\n\n if (typeof fetch !== 'function') return;\n\n this.sending = true;\n // No custom headers + a string body (Content-Type defaults to text/plain)\n // => CORS-safelisted simple request => no preflight.\n fetch(this.url, {\n method: 'POST',\n body,\n keepalive: true,\n mode: 'cors',\n credentials: 'omit',\n })\n .then((res) => {\n this.sending = false;\n if (res.status >= 500) this.requeue(batch);\n else this.failures = 0;\n })\n .catch(() => {\n this.sending = false;\n this.requeue(batch);\n });\n }\n\n private requeue(batch: MonitoredEvent[]): void {\n this.failures++;\n if (this.failures > 5) {\n this.failures = 0;\n return; // give up on this batch to avoid an infinite retry loop\n }\n const room = this.opts.maxQueueSize - this.queue.length;\n if (room > 0) this.queue.unshift(...batch.slice(-room));\n const delay = Math.min(30000, 1000 * Math.pow(2, this.failures));\n setTimeout(() => this.flush(), delay);\n }\n\n private envelope(events: MonitoredEvent[]) {\n return {\n sdk: { name: '@accelerup-llc/web-monitor', version: VERSION },\n project_id: this.dsn.projectId,\n sent_at: Date.now(),\n events,\n };\n }\n}\n","/**\n * cyrb53 — a fast, well-distributed non-cryptographic hash. We only need it\n * client-side for de-duplication / grouping; the backend computes the\n * authoritative SHA-256 fingerprint. Tiny and dependency-free.\n */\nexport function cyrb53(str: string, seed = 0): string {\n let h1 = 0xdeadbeef ^ seed;\n let h2 = 0x41c6ce57 ^ seed;\n for (let i = 0; i < str.length; i++) {\n const ch = str.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(13, '0');\n}\n\n/** Keep the top N stack frames for stable grouping. */\nexport function topFrames(stack?: string, n = 3): string {\n if (!stack) return '';\n return stack.split('\\n').slice(0, n + 1).join('\\n');\n}\n\n/**\n * Normalizes volatile bits (line/col numbers, addresses, long ids, urls) so\n * that the \"same\" error groups together regardless of run-to-run noise.\n */\nexport function makeFingerprint(parts: Array<string | undefined>): string {\n const normalized = parts\n .filter(Boolean)\n .join('\\n')\n .replace(/:\\d+:\\d+/g, '')\n .replace(/0x[0-9a-fA-F]+/g, '0x')\n .replace(/\\b\\d{4,}\\b/g, 'N')\n .replace(/https?:\\/\\/[^\\s)]+/g, (m) => {\n try {\n const u = new URL(m);\n return u.origin + u.pathname;\n } catch {\n return m;\n }\n });\n return cyrb53(normalized);\n}\n","/**\n * Strips query string and hash from a URL to avoid leaking tokens / PII that\n * commonly live in query params. Only origin + pathname is kept.\n */\nexport function scrubUrl(url: string): string {\n if (!url) return '';\n try {\n const u = new URL(url);\n return u.origin + u.pathname;\n } catch {\n return url.split('?')[0].split('#')[0];\n }\n}\n","let sessionId: string | null = null;\n\nexport function uuid(): string {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n } catch {\n /* fall through to manual */\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/** Stable id for the current page session (memory-only, no storage). */\nexport function getSessionId(): string {\n if (!sessionId) sessionId = uuid();\n return sessionId;\n}\n","export const GLOBAL_KEY = '__ACCELERUP_WEB_MONITOR__';\n\nfunction bind(method: 'log' | 'warn' | 'error'): (...args: unknown[]) => void {\n if (typeof console !== 'undefined' && typeof console[method] === 'function') {\n return console[method].bind(console);\n }\n return () => {\n /* noop */\n };\n}\n\n/**\n * References to the real console methods, captured at module load — i.e.\n * BEFORE we patch console. All internal logging must go through these so the\n * SDK never feeds its own output back into the capture pipeline.\n */\nexport const originalConsole = {\n log: bind('log'),\n warn: bind('warn'),\n error: bind('error'),\n};\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n","import type { Level, MonitorConfig, MonitoredEvent, UserContext } from '../types';\nimport type { ParsedDsn } from '../dsn';\nimport type { RawEvent } from './handlers';\nimport { installHandlers } from './handlers';\nimport { Dedupe, RateLimiter } from './dedup';\nimport { Transport } from '../transport/transport';\nimport { makeFingerprint, topFrames } from './fingerprint';\nimport { scrubUrl } from './scrub';\nimport { getSessionId, uuid } from './session';\nimport { isBrowser, originalConsole } from '../utils';\n\nexport interface ResolvedConfig extends MonitorConfig {\n sampleRate: number;\n warningSampleRate: number;\n maxStackChars: number;\n dedupeWindow: number;\n maxEventsPerMinute: number;\n flushInterval: number;\n maxBatchSize: number;\n maxQueueSize: number;\n}\n\nexport class Monitor {\n private readonly transport: Transport;\n private readonly dedupe: Dedupe;\n private readonly rate: RateLimiter;\n private uninstall?: () => void;\n private inCapture = false;\n\n constructor(private config: ResolvedConfig, private dsn: ParsedDsn) {\n this.transport = new Transport(dsn, {\n flushInterval: config.flushInterval,\n maxBatchSize: config.maxBatchSize,\n maxQueueSize: config.maxQueueSize,\n });\n this.dedupe = new Dedupe(config.dedupeWindow);\n this.rate = new RateLimiter(config.maxEventsPerMinute);\n }\n\n start(): void {\n if (this.uninstall) return;\n this.uninstall = installHandlers(this.config, (raw) => this.capture(raw));\n this.installLifecycle();\n if (this.config.debug) {\n originalConsole.log('[accelerup] monitor started', { release: this.config.release });\n }\n }\n\n /** The single funnel every capture source flows through. Never throws. */\n capture(raw: RawEvent): void {\n if (this.inCapture) return; // re-entrancy guard against feedback loops\n this.inCapture = true;\n try {\n if (!raw.message) return;\n // Never report our own ingest traffic.\n if (raw.stack && raw.stack.indexOf(this.dsn.ingestUrl) !== -1) return;\n if (this.isIgnored(raw.message)) return;\n\n const url = scrubUrl(typeof location !== 'undefined' ? location.href : '');\n if (!this.passUrlFilters(raw.stack, url)) return;\n\n const rate = raw.level === 'warning' ? this.config.warningSampleRate : this.config.sampleRate;\n if (rate < 1 && Math.random() > rate) return;\n\n const stack = raw.stack ? raw.stack.slice(0, this.config.maxStackChars) : undefined;\n const fingerprint = makeFingerprint([raw.type, raw.message, topFrames(stack)]);\n\n const now = Date.now();\n if (!this.dedupe.shouldSend(fingerprint, now)) return;\n if (!this.rate.allow(now)) return;\n\n const event: MonitoredEvent = {\n event_id: uuid(),\n level: raw.level,\n message: raw.message.slice(0, 2000),\n type: raw.type,\n stack,\n source: raw.source,\n fingerprint,\n url,\n filename: raw.filename,\n lineno: raw.lineno,\n colno: raw.colno,\n release: this.config.release,\n environment: this.config.environment,\n session_id: getSessionId(),\n user: this.config.user,\n user_agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n timestamp: now,\n tags: this.config.tags,\n };\n\n let final: MonitoredEvent | null = event;\n if (this.config.beforeSend) {\n try {\n final = this.config.beforeSend(event);\n } catch {\n final = event;\n }\n }\n if (!final) return;\n\n this.transport.add(final);\n if (this.config.debug) originalConsole.log('[accelerup] captured', final.level, final.message);\n } catch {\n /* swallow — capture must never break the host app */\n } finally {\n this.inCapture = false;\n }\n }\n\n captureException(\n error: unknown,\n opts?: { level?: Level; source?: RawEvent['source']; tags?: Record<string, string> },\n ): void {\n let message = 'Error';\n let stack: string | undefined;\n let type: string | undefined;\n if (error instanceof Error) {\n message = error.message;\n stack = error.stack;\n type = error.name;\n } else if (typeof error === 'string') {\n message = error;\n } else if (error != null) {\n try {\n message = JSON.stringify(error);\n } catch {\n message = String(error);\n }\n }\n this.capture({\n level: opts?.level ?? 'error',\n source: opts?.source ?? 'manual',\n message,\n stack,\n type,\n });\n }\n\n captureMessage(message: string, level: Level = 'warning'): void {\n this.capture({ level, source: 'manual', message });\n }\n\n setUser(user: UserContext | undefined): void {\n this.config.user = user;\n }\n\n flush(): void {\n this.transport.flush();\n }\n\n close(): void {\n this.transport.flush(true);\n if (this.uninstall) {\n this.uninstall();\n this.uninstall = undefined;\n }\n }\n\n private isIgnored(message: string): boolean {\n const list = this.config.ignoreErrors;\n if (!list) return false;\n return list.some((p) => (typeof p === 'string' ? message.indexOf(p) !== -1 : p.test(message)));\n }\n\n private passUrlFilters(stack: string | undefined, url: string): boolean {\n const hay = `${stack || ''} ${url}`;\n const { denyUrls, allowUrls } = this.config;\n if (denyUrls && denyUrls.some((p) => match(p, hay))) return false;\n if (allowUrls && allowUrls.length > 0 && !allowUrls.some((p) => match(p, hay))) return false;\n return true;\n }\n\n private installLifecycle(): void {\n if (!isBrowser()) return;\n const beacon = () => this.transport.flush(true);\n window.addEventListener('pagehide', beacon);\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') this.transport.flush(true);\n });\n }\n}\n\nfunction match(p: string | RegExp, value: string): boolean {\n return typeof p === 'string' ? value.indexOf(p) !== -1 : p.test(value);\n}\n","import type { MonitorConfig } from './types';\n\nexport interface ParsedDsn {\n publicKey: string;\n projectId: string;\n ingestUrl: string;\n}\n\n/**\n * Resolves the ingest target from config. Prefers the explicit\n * `ingestUrl` + `key` pair (env-friendly); falls back to a `dsn` string.\n */\nexport function resolveEndpoint(config: MonitorConfig): ParsedDsn | null {\n if (config.ingestUrl && config.key) {\n return {\n publicKey: config.key,\n projectId: config.project || '',\n ingestUrl: config.ingestUrl.replace(/\\/+$/, ''),\n };\n }\n if (config.dsn) {\n return parseDsn(config.dsn, config.endpoint);\n }\n return null;\n}\n\n/**\n * Parses a DSN of the form `https://PUBLIC_KEY@host[:port]/PROJECT_ID`.\n * Falls back to `?key=` / `?project=` query params when present.\n */\nexport function parseDsn(dsn: string, endpointOverride?: string): ParsedDsn | null {\n try {\n const u = new URL(dsn);\n const publicKey = u.username || u.searchParams.get('key') || '';\n const projectId =\n u.pathname.replace(/^\\/+/, '').split('/')[0] ||\n u.searchParams.get('project') ||\n '';\n\n if (!publicKey || !projectId) return null;\n\n const ingestUrl = endpointOverride\n ? endpointOverride.replace(/\\/+$/, '')\n : `${u.protocol}//${u.host}/ingest/web-errors`;\n\n return { publicKey, projectId, ingestUrl };\n } catch {\n return null;\n }\n}\n","import type { MonitorConfig } from './types';\nimport type { ResolvedConfig } from './core/client';\nimport { Monitor } from './core/client';\nimport { resolveEndpoint } from './dsn';\nimport { GLOBAL_KEY, isBrowser, originalConsole } from './utils';\nimport { VERSION } from './version';\n\ninterface GlobalRegistry {\n __initialized: boolean;\n client?: Monitor;\n version: string;\n}\n\n/**\n * Initializes the monitor. Safe to call multiple times — the second and later\n * calls return the existing instance (idempotent across HMR, double imports,\n * and App Router + Pages Router both mounting). A no-op on the server (SSR).\n */\nexport function init(config: MonitorConfig): Monitor | undefined {\n if (!isBrowser()) return undefined;\n if (config.enabled === false) return undefined;\n if (!config || (!config.dsn && !(config.ingestUrl && config.key))) {\n originalConsole.warn('[accelerup] init() needs either { ingestUrl, key } or { dsn } — skipping.');\n return undefined;\n }\n\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n const existing = w[GLOBAL_KEY];\n if (existing && existing.__initialized && existing.client) {\n return existing.client;\n }\n\n const dsn = resolveEndpoint(config);\n if (!dsn) {\n originalConsole.warn('[accelerup] invalid config — provide { ingestUrl, key } or a valid dsn');\n return undefined;\n }\n\n const client = new Monitor(resolveConfig(config), dsn);\n w[GLOBAL_KEY] = { __initialized: true, client, version: VERSION };\n client.start();\n return client;\n}\n\nexport function getClient(): Monitor | undefined {\n if (!isBrowser()) return undefined;\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n return w[GLOBAL_KEY]?.client;\n}\n\nfunction resolveConfig(c: MonitorConfig): ResolvedConfig {\n return {\n ...c,\n sampleRate: c.sampleRate ?? 1,\n warningSampleRate: c.warningSampleRate ?? 1,\n maxStackChars: c.maxStackChars ?? 4000,\n dedupeWindow: c.dedupeWindow ?? 5000,\n maxEventsPerMinute: c.maxEventsPerMinute ?? 30,\n flushInterval: c.flushInterval ?? 5000,\n maxBatchSize: c.maxBatchSize ?? 20,\n maxQueueSize: c.maxQueueSize ?? 100,\n };\n}\n","import type { Level, UserContext } from './types';\nimport { getClient } from './init';\n\n/** Manually report an error/exception. No-op if init() hasn't run. */\nexport function captureError(\n error: unknown,\n opts?: { level?: Level; tags?: Record<string, string> },\n): void {\n getClient()?.captureException(error, opts);\n}\n\n/** Manually report a message (defaults to warning level). */\nexport function captureMessage(message: string, level: Level = 'warning'): void {\n getClient()?.captureMessage(message, level);\n}\n\n/** Attach (or clear) the current user context for subsequent events. */\nexport function setUser(user: UserContext | undefined): void {\n getClient()?.setUser(user);\n}\n\n/** Force an immediate flush of the buffered events. */\nexport function flush(): void {\n getClient()?.flush();\n}\n"]}
@@ -0,0 +1,170 @@
1
+ type Level = 'error' | 'warning';
2
+ type EventSource = 'onerror' | 'unhandledrejection' | 'console' | 'react' | 'manual';
3
+ interface UserContext {
4
+ id?: string;
5
+ email?: string;
6
+ username?: string;
7
+ }
8
+ /** A fully enriched event, ready to be sent to the ingest endpoint. */
9
+ interface MonitoredEvent {
10
+ event_id: string;
11
+ level: Level;
12
+ message: string;
13
+ type?: string;
14
+ stack?: string;
15
+ source: EventSource;
16
+ fingerprint: string;
17
+ url: string;
18
+ filename?: string;
19
+ lineno?: number;
20
+ colno?: number;
21
+ release?: string;
22
+ environment?: string;
23
+ session_id: string;
24
+ user?: UserContext;
25
+ user_agent: string;
26
+ timestamp: number;
27
+ tags?: Record<string, string>;
28
+ }
29
+ interface MonitorConfig {
30
+ /**
31
+ * The full ingest URL, e.g. `https://api.accelerup.com/ingest/web-errors`.
32
+ * Use together with `key`. This is the recommended, env-friendly setup.
33
+ */
34
+ ingestUrl?: string;
35
+ /**
36
+ * The public ingest key (write-only, safe to ship to the browser). Maps to an
37
+ * org on the backend. Use together with `ingestUrl`.
38
+ */
39
+ key?: string;
40
+ /** Optional project/app identifier sent as a tag alongside each event. */
41
+ project?: string;
42
+ /**
43
+ * Alternative to `ingestUrl` + `key`: a DSN of the form
44
+ * `https://PUBLIC_KEY@host/PROJECT_ID`. If set, it takes precedence.
45
+ */
46
+ dsn?: string;
47
+ /** Override the full ingest URL (otherwise derived from the DSN host). */
48
+ endpoint?: string;
49
+ /** App release/version (git sha, semver). Used to group issues per release. */
50
+ release?: string;
51
+ /** e.g. "production" | "staging" | "development". */
52
+ environment?: string;
53
+ /** Hard kill switch. When false, init() is a no-op. */
54
+ enabled?: boolean;
55
+ /** Capture uncaught errors via window 'error'. Default: true. */
56
+ captureError?: boolean;
57
+ /** Capture unhandled promise rejections. Default: true. */
58
+ captureUnhandledRejection?: boolean;
59
+ /** Patch console.error / console.warn. Default: both true. */
60
+ captureConsole?: boolean | {
61
+ error?: boolean;
62
+ warn?: boolean;
63
+ };
64
+ /** Drop events whose message matches any of these. */
65
+ ignoreErrors?: (string | RegExp)[];
66
+ /** Drop events whose stack/url matches any of these. */
67
+ denyUrls?: (string | RegExp)[];
68
+ /** If set, only keep events whose stack/url matches one of these. */
69
+ allowUrls?: (string | RegExp)[];
70
+ /** 0..1 sample rate for errors. Default: 1. */
71
+ sampleRate?: number;
72
+ /** 0..1 sample rate for warnings. Default: 1. */
73
+ warningSampleRate?: number;
74
+ /** Flush interval in ms. Default: 5000. */
75
+ flushInterval?: number;
76
+ /** Max events per network batch. Default: 20. */
77
+ maxBatchSize?: number;
78
+ /** Max events buffered in memory (oldest dropped past this). Default: 100. */
79
+ maxQueueSize?: number;
80
+ /** Token-bucket cap of events sent per minute. Default: 30. */
81
+ maxEventsPerMinute?: number;
82
+ /** Window (ms) in which identical events are de-duplicated. Default: 5000. */
83
+ dedupeWindow?: number;
84
+ /** Truncate stack traces to this many chars. Default: 4000. */
85
+ maxStackChars?: number;
86
+ user?: UserContext;
87
+ tags?: Record<string, string>;
88
+ /** Last-chance hook. Return null to drop, or a modified event to send. */
89
+ beforeSend?: (event: MonitoredEvent) => MonitoredEvent | null;
90
+ /** Verbose internal logging (uses the original console, never captured). */
91
+ debug?: boolean;
92
+ }
93
+
94
+ interface ParsedDsn {
95
+ publicKey: string;
96
+ projectId: string;
97
+ ingestUrl: string;
98
+ }
99
+
100
+ /** A partial event produced by a capture source, before enrichment. */
101
+ interface RawEvent {
102
+ level: Level;
103
+ source: EventSource;
104
+ message: string;
105
+ stack?: string;
106
+ type?: string;
107
+ filename?: string;
108
+ lineno?: number;
109
+ colno?: number;
110
+ }
111
+
112
+ interface ResolvedConfig extends MonitorConfig {
113
+ sampleRate: number;
114
+ warningSampleRate: number;
115
+ maxStackChars: number;
116
+ dedupeWindow: number;
117
+ maxEventsPerMinute: number;
118
+ flushInterval: number;
119
+ maxBatchSize: number;
120
+ maxQueueSize: number;
121
+ }
122
+ declare class Monitor {
123
+ private config;
124
+ private dsn;
125
+ private readonly transport;
126
+ private readonly dedupe;
127
+ private readonly rate;
128
+ private uninstall?;
129
+ private inCapture;
130
+ constructor(config: ResolvedConfig, dsn: ParsedDsn);
131
+ start(): void;
132
+ /** The single funnel every capture source flows through. Never throws. */
133
+ capture(raw: RawEvent): void;
134
+ captureException(error: unknown, opts?: {
135
+ level?: Level;
136
+ source?: RawEvent['source'];
137
+ tags?: Record<string, string>;
138
+ }): void;
139
+ captureMessage(message: string, level?: Level): void;
140
+ setUser(user: UserContext | undefined): void;
141
+ flush(): void;
142
+ close(): void;
143
+ private isIgnored;
144
+ private passUrlFilters;
145
+ private installLifecycle;
146
+ }
147
+
148
+ /**
149
+ * Initializes the monitor. Safe to call multiple times — the second and later
150
+ * calls return the existing instance (idempotent across HMR, double imports,
151
+ * and App Router + Pages Router both mounting). A no-op on the server (SSR).
152
+ */
153
+ declare function init(config: MonitorConfig): Monitor | undefined;
154
+ declare function getClient(): Monitor | undefined;
155
+
156
+ /** Manually report an error/exception. No-op if init() hasn't run. */
157
+ declare function captureError(error: unknown, opts?: {
158
+ level?: Level;
159
+ tags?: Record<string, string>;
160
+ }): void;
161
+ /** Manually report a message (defaults to warning level). */
162
+ declare function captureMessage(message: string, level?: Level): void;
163
+ /** Attach (or clear) the current user context for subsequent events. */
164
+ declare function setUser(user: UserContext | undefined): void;
165
+ /** Force an immediate flush of the buffered events. */
166
+ declare function flush(): void;
167
+
168
+ declare const VERSION = "0.1.0";
169
+
170
+ export { type EventSource, type Level, type MonitorConfig, type MonitoredEvent, type UserContext, VERSION, captureError, captureMessage, flush, getClient, init, setUser };
@@ -0,0 +1,170 @@
1
+ type Level = 'error' | 'warning';
2
+ type EventSource = 'onerror' | 'unhandledrejection' | 'console' | 'react' | 'manual';
3
+ interface UserContext {
4
+ id?: string;
5
+ email?: string;
6
+ username?: string;
7
+ }
8
+ /** A fully enriched event, ready to be sent to the ingest endpoint. */
9
+ interface MonitoredEvent {
10
+ event_id: string;
11
+ level: Level;
12
+ message: string;
13
+ type?: string;
14
+ stack?: string;
15
+ source: EventSource;
16
+ fingerprint: string;
17
+ url: string;
18
+ filename?: string;
19
+ lineno?: number;
20
+ colno?: number;
21
+ release?: string;
22
+ environment?: string;
23
+ session_id: string;
24
+ user?: UserContext;
25
+ user_agent: string;
26
+ timestamp: number;
27
+ tags?: Record<string, string>;
28
+ }
29
+ interface MonitorConfig {
30
+ /**
31
+ * The full ingest URL, e.g. `https://api.accelerup.com/ingest/web-errors`.
32
+ * Use together with `key`. This is the recommended, env-friendly setup.
33
+ */
34
+ ingestUrl?: string;
35
+ /**
36
+ * The public ingest key (write-only, safe to ship to the browser). Maps to an
37
+ * org on the backend. Use together with `ingestUrl`.
38
+ */
39
+ key?: string;
40
+ /** Optional project/app identifier sent as a tag alongside each event. */
41
+ project?: string;
42
+ /**
43
+ * Alternative to `ingestUrl` + `key`: a DSN of the form
44
+ * `https://PUBLIC_KEY@host/PROJECT_ID`. If set, it takes precedence.
45
+ */
46
+ dsn?: string;
47
+ /** Override the full ingest URL (otherwise derived from the DSN host). */
48
+ endpoint?: string;
49
+ /** App release/version (git sha, semver). Used to group issues per release. */
50
+ release?: string;
51
+ /** e.g. "production" | "staging" | "development". */
52
+ environment?: string;
53
+ /** Hard kill switch. When false, init() is a no-op. */
54
+ enabled?: boolean;
55
+ /** Capture uncaught errors via window 'error'. Default: true. */
56
+ captureError?: boolean;
57
+ /** Capture unhandled promise rejections. Default: true. */
58
+ captureUnhandledRejection?: boolean;
59
+ /** Patch console.error / console.warn. Default: both true. */
60
+ captureConsole?: boolean | {
61
+ error?: boolean;
62
+ warn?: boolean;
63
+ };
64
+ /** Drop events whose message matches any of these. */
65
+ ignoreErrors?: (string | RegExp)[];
66
+ /** Drop events whose stack/url matches any of these. */
67
+ denyUrls?: (string | RegExp)[];
68
+ /** If set, only keep events whose stack/url matches one of these. */
69
+ allowUrls?: (string | RegExp)[];
70
+ /** 0..1 sample rate for errors. Default: 1. */
71
+ sampleRate?: number;
72
+ /** 0..1 sample rate for warnings. Default: 1. */
73
+ warningSampleRate?: number;
74
+ /** Flush interval in ms. Default: 5000. */
75
+ flushInterval?: number;
76
+ /** Max events per network batch. Default: 20. */
77
+ maxBatchSize?: number;
78
+ /** Max events buffered in memory (oldest dropped past this). Default: 100. */
79
+ maxQueueSize?: number;
80
+ /** Token-bucket cap of events sent per minute. Default: 30. */
81
+ maxEventsPerMinute?: number;
82
+ /** Window (ms) in which identical events are de-duplicated. Default: 5000. */
83
+ dedupeWindow?: number;
84
+ /** Truncate stack traces to this many chars. Default: 4000. */
85
+ maxStackChars?: number;
86
+ user?: UserContext;
87
+ tags?: Record<string, string>;
88
+ /** Last-chance hook. Return null to drop, or a modified event to send. */
89
+ beforeSend?: (event: MonitoredEvent) => MonitoredEvent | null;
90
+ /** Verbose internal logging (uses the original console, never captured). */
91
+ debug?: boolean;
92
+ }
93
+
94
+ interface ParsedDsn {
95
+ publicKey: string;
96
+ projectId: string;
97
+ ingestUrl: string;
98
+ }
99
+
100
+ /** A partial event produced by a capture source, before enrichment. */
101
+ interface RawEvent {
102
+ level: Level;
103
+ source: EventSource;
104
+ message: string;
105
+ stack?: string;
106
+ type?: string;
107
+ filename?: string;
108
+ lineno?: number;
109
+ colno?: number;
110
+ }
111
+
112
+ interface ResolvedConfig extends MonitorConfig {
113
+ sampleRate: number;
114
+ warningSampleRate: number;
115
+ maxStackChars: number;
116
+ dedupeWindow: number;
117
+ maxEventsPerMinute: number;
118
+ flushInterval: number;
119
+ maxBatchSize: number;
120
+ maxQueueSize: number;
121
+ }
122
+ declare class Monitor {
123
+ private config;
124
+ private dsn;
125
+ private readonly transport;
126
+ private readonly dedupe;
127
+ private readonly rate;
128
+ private uninstall?;
129
+ private inCapture;
130
+ constructor(config: ResolvedConfig, dsn: ParsedDsn);
131
+ start(): void;
132
+ /** The single funnel every capture source flows through. Never throws. */
133
+ capture(raw: RawEvent): void;
134
+ captureException(error: unknown, opts?: {
135
+ level?: Level;
136
+ source?: RawEvent['source'];
137
+ tags?: Record<string, string>;
138
+ }): void;
139
+ captureMessage(message: string, level?: Level): void;
140
+ setUser(user: UserContext | undefined): void;
141
+ flush(): void;
142
+ close(): void;
143
+ private isIgnored;
144
+ private passUrlFilters;
145
+ private installLifecycle;
146
+ }
147
+
148
+ /**
149
+ * Initializes the monitor. Safe to call multiple times — the second and later
150
+ * calls return the existing instance (idempotent across HMR, double imports,
151
+ * and App Router + Pages Router both mounting). A no-op on the server (SSR).
152
+ */
153
+ declare function init(config: MonitorConfig): Monitor | undefined;
154
+ declare function getClient(): Monitor | undefined;
155
+
156
+ /** Manually report an error/exception. No-op if init() hasn't run. */
157
+ declare function captureError(error: unknown, opts?: {
158
+ level?: Level;
159
+ tags?: Record<string, string>;
160
+ }): void;
161
+ /** Manually report a message (defaults to warning level). */
162
+ declare function captureMessage(message: string, level?: Level): void;
163
+ /** Attach (or clear) the current user context for subsequent events. */
164
+ declare function setUser(user: UserContext | undefined): void;
165
+ /** Force an immediate flush of the buffered events. */
166
+ declare function flush(): void;
167
+
168
+ declare const VERSION = "0.1.0";
169
+
170
+ export { type EventSource, type Level, type MonitorConfig, type MonitoredEvent, type UserContext, VERSION, captureError, captureMessage, flush, getClient, init, setUser };
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ function b(t,e){let n=[];if(t.captureError!==false){let i=s=>{try{let o=s.target;if(o&&o!==window&&o.nodeName)return;let a=s.error;e({level:"error",source:"onerror",message:s.message||a&&a.message||"Unknown error",stack:a&&a.stack,type:a&&a.name,filename:s.filename,lineno:s.lineno,colno:s.colno});}catch{}};window.addEventListener("error",i,true),n.push(()=>window.removeEventListener("error",i,true));}if(t.captureUnhandledRejection!==false){let i=s=>{try{let o=s.reason,a="Unhandled Promise Rejection",u,E;o instanceof Error?(a=`${a}: ${o.message}`,u=o.stack,E=o.name):typeof o=="string"?a=`${a}: ${o}`:o!=null&&(a=`${a}: ${k(o)}`),e({level:"error",source:"unhandledrejection",message:a,stack:u,type:E});}catch{}};window.addEventListener("unhandledrejection",i),n.push(()=>window.removeEventListener("unhandledrejection",i));}let r=I(t.captureConsole);return ["error","warn"].forEach(i=>{if(!r[i])return;let s=console[i],o=i==="warn"?"warning":"error";console[i]=function(...u){s.apply(console,u);try{e(j(o,u));}catch{}},n.push(()=>{console[i]=s;});}),()=>n.forEach(i=>{try{i();}catch{}})}function I(t){return t===false?{error:false,warn:false}:t===void 0||t===true?{error:true,warn:true}:{error:t.error!==false,warn:t.warn!==false}}function j(t,e){let n,r,i=e.find(o=>o instanceof Error);i&&(n=i.stack,r=i.name);let s=e.map(z).join(" ").slice(0,2e3)||(t==="warning"?"console.warn":"console.error");return {level:t,source:"console",message:s,stack:n,type:r}}function z(t){return typeof t=="string"?t:t instanceof Error?t.message:k(t)}function k(t){try{return typeof t=="object"&&t!==null?JSON.stringify(t):String(t)}catch{return Object.prototype.toString.call(t)}}var p=class{constructor(e){this.windowMs=e;this.seen=new Map;}shouldSend(e,n){let r=this.seen.get(e);if(r!==void 0&&n-r<this.windowMs)return false;if(this.seen.set(e,n),this.seen.size>200)for(let[i,s]of this.seen)n-s>this.windowMs&&this.seen.delete(i);return true}},h=class{constructor(e){this.maxPerMin=e;this.tokens=e,this.last=Date.now();}allow(e){let n=e-this.last;return this.last=e,this.tokens=Math.min(this.maxPerMin,this.tokens+n/6e4*this.maxPerMin),this.tokens>=1?(this.tokens-=1,true):false}};var f="0.1.0";var m=class{constructor(e,n){this.dsn=e;this.opts=n;this.queue=[];this.timer=null;this.sending=false;this.failures=0;let r=e.ingestUrl.indexOf("?")===-1?"?":"&";this.url=`${e.ingestUrl}${r}key=${encodeURIComponent(e.publicKey)}&project=${encodeURIComponent(e.projectId)}`;}add(e){this.queue.length>=this.opts.maxQueueSize&&this.queue.shift(),this.queue.push(e),this.queue.length>=this.opts.maxBatchSize?this.flush():this.schedule();}schedule(){this.timer==null&&(this.timer=setTimeout(()=>{this.timer=null,this.flush();},this.opts.flushInterval));}flush(e=false){if(this.timer!=null&&(clearTimeout(this.timer),this.timer=null),this.queue.length===0||this.sending&&!e)return;let n=this.queue.splice(0,this.opts.maxBatchSize),r=JSON.stringify(this.envelope(n));if(e&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){try{navigator.sendBeacon(this.url,new Blob([r],{type:"text/plain;charset=UTF-8"}))||this.queue.unshift(...n);}catch{this.queue.unshift(...n);}return}typeof fetch=="function"&&(this.sending=true,fetch(this.url,{method:"POST",body:r,keepalive:true,mode:"cors",credentials:"omit"}).then(i=>{this.sending=false,i.status>=500?this.requeue(n):this.failures=0;}).catch(()=>{this.sending=false,this.requeue(n);}));}requeue(e){if(this.failures++,this.failures>5){this.failures=0;return}let n=this.opts.maxQueueSize-this.queue.length;n>0&&this.queue.unshift(...e.slice(-n));let r=Math.min(3e4,1e3*Math.pow(2,this.failures));setTimeout(()=>this.flush(),r);}envelope(e){return {sdk:{name:"@accelerup-llc/web-monitor",version:f},project_id:this.dsn.projectId,sent_at:Date.now(),events:e}}};function P(t,e=0){let n=3735928559^e,r=1103547991^e;for(let i=0;i<t.length;i++){let s=t.charCodeAt(i);n=Math.imul(n^s,2654435761),r=Math.imul(r^s,1597334677);}return n=Math.imul(n^n>>>16,2246822507)^Math.imul(r^r>>>13,3266489909),r=Math.imul(r^r>>>16,2246822507)^Math.imul(n^n>>>13,3266489909),(4294967296*(2097151&r)+(n>>>0)).toString(16).padStart(13,"0")}function M(t,e=3){return t?t.split(`
2
+ `).slice(0,e+1).join(`
3
+ `):""}function S(t){let e=t.filter(Boolean).join(`
4
+ `).replace(/:\d+:\d+/g,"").replace(/0x[0-9a-fA-F]+/g,"0x").replace(/\b\d{4,}\b/g,"N").replace(/https?:\/\/[^\s)]+/g,n=>{try{let r=new URL(n);return r.origin+r.pathname}catch{return n}});return P(e)}function C(t){if(!t)return "";try{let e=new URL(t);return e.origin+e.pathname}catch{return t.split("?")[0].split("#")[0]}}var x=null;function y(){try{if(typeof crypto<"u"&&typeof crypto.randomUUID=="function")return crypto.randomUUID()}catch{}return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,t=>{let e=Math.random()*16|0;return (t==="x"?e:e&3|8).toString(16)})}function R(){return x||(x=y()),x}var g="__ACCELERUP_WEB_MONITOR__";function w(t){return typeof console<"u"&&typeof console[t]=="function"?console[t].bind(console):()=>{}}var l={log:w("log"),warn:w("warn"),error:w("error")};function d(){return typeof window<"u"&&typeof document<"u"}var v=class{constructor(e,n){this.config=e;this.dsn=n;this.inCapture=false;this.transport=new m(n,{flushInterval:e.flushInterval,maxBatchSize:e.maxBatchSize,maxQueueSize:e.maxQueueSize}),this.dedupe=new p(e.dedupeWindow),this.rate=new h(e.maxEventsPerMinute);}start(){this.uninstall||(this.uninstall=b(this.config,e=>this.capture(e)),this.installLifecycle(),this.config.debug&&l.log("[accelerup] monitor started",{release:this.config.release}));}capture(e){if(!this.inCapture){this.inCapture=true;try{if(!e.message||e.stack&&e.stack.indexOf(this.dsn.ingestUrl)!==-1||this.isIgnored(e.message))return;let n=C(typeof location<"u"?location.href:"");if(!this.passUrlFilters(e.stack,n))return;let r=e.level==="warning"?this.config.warningSampleRate:this.config.sampleRate;if(r<1&&Math.random()>r)return;let i=e.stack?e.stack.slice(0,this.config.maxStackChars):void 0,s=S([e.type,e.message,M(i)]),o=Date.now();if(!this.dedupe.shouldSend(s,o)||!this.rate.allow(o))return;let a={event_id:y(),level:e.level,message:e.message.slice(0,2e3),type:e.type,stack:i,source:e.source,fingerprint:s,url:n,filename:e.filename,lineno:e.lineno,colno:e.colno,release:this.config.release,environment:this.config.environment,session_id:R(),user:this.config.user,user_agent:typeof navigator<"u"?navigator.userAgent:"",timestamp:o,tags:this.config.tags},u=a;if(this.config.beforeSend)try{u=this.config.beforeSend(a);}catch{u=a;}if(!u)return;this.transport.add(u),this.config.debug&&l.log("[accelerup] captured",u.level,u.message);}catch{}finally{this.inCapture=false;}}}captureException(e,n){let r="Error",i,s;if(e instanceof Error)r=e.message,i=e.stack,s=e.name;else if(typeof e=="string")r=e;else if(e!=null)try{r=JSON.stringify(e);}catch{r=String(e);}this.capture({level:n?.level??"error",source:n?.source??"manual",message:r,stack:i,type:s});}captureMessage(e,n="warning"){this.capture({level:n,source:"manual",message:e});}setUser(e){this.config.user=e;}flush(){this.transport.flush();}close(){this.transport.flush(true),this.uninstall&&(this.uninstall(),this.uninstall=void 0);}isIgnored(e){let n=this.config.ignoreErrors;return n?n.some(r=>typeof r=="string"?e.indexOf(r)!==-1:r.test(e)):false}passUrlFilters(e,n){let r=`${e||""} ${n}`,{denyUrls:i,allowUrls:s}=this.config;return !(i&&i.some(o=>U(o,r))||s&&s.length>0&&!s.some(o=>U(o,r)))}installLifecycle(){if(!d())return;let e=()=>this.transport.flush(true);window.addEventListener("pagehide",e),document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&this.transport.flush(true);});}};function U(t,e){return typeof t=="string"?e.indexOf(t)!==-1:t.test(e)}function L(t){return t.ingestUrl&&t.key?{publicKey:t.key,projectId:t.project||"",ingestUrl:t.ingestUrl.replace(/\/+$/,"")}:t.dsn?_(t.dsn,t.endpoint):null}function _(t,e){try{let n=new URL(t),r=n.username||n.searchParams.get("key")||"",i=n.pathname.replace(/^\/+/,"").split("/")[0]||n.searchParams.get("project")||"";if(!r||!i)return null;let s=e?e.replace(/\/+$/,""):`${n.protocol}//${n.host}/ingest/web-errors`;return {publicKey:r,projectId:i,ingestUrl:s}}catch{return null}}function O(t){if(!d()||t.enabled===false)return;if(!t||!t.dsn&&!(t.ingestUrl&&t.key)){l.warn("[accelerup] init() needs either { ingestUrl, key } or { dsn } \u2014 skipping.");return}let e=window,n=e[g];if(n&&n.__initialized&&n.client)return n.client;let r=L(t);if(!r){l.warn("[accelerup] invalid config \u2014 provide { ingestUrl, key } or a valid dsn");return}let i=new v(B(t),r);return e[g]={__initialized:true,client:i,version:f},i.start(),i}function c(){return d()?window[g]?.client:void 0}function B(t){return {...t,sampleRate:t.sampleRate??1,warningSampleRate:t.warningSampleRate??1,maxStackChars:t.maxStackChars??4e3,dedupeWindow:t.dedupeWindow??5e3,maxEventsPerMinute:t.maxEventsPerMinute??30,flushInterval:t.flushInterval??5e3,maxBatchSize:t.maxBatchSize??20,maxQueueSize:t.maxQueueSize??100}}function $(t,e){c()?.captureException(t,e);}function q(t,e="warning"){c()?.captureMessage(t,e);}function D(t){c()?.setUser(t);}function N(){c()?.flush();}
5
+ export{f as VERSION,$ as captureError,q as captureMessage,N as flush,c as getClient,O as init,D as setUser};//# sourceMappingURL=index.js.map
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/handlers.ts","../src/core/dedup.ts","../src/version.ts","../src/transport/transport.ts","../src/core/fingerprint.ts","../src/core/scrub.ts","../src/core/session.ts","../src/utils.ts","../src/core/client.ts","../src/dsn.ts","../src/init.ts","../src/capture.ts"],"names":["installHandlers","config","capture","cleanups","onError","event","target","err","onRejection","reason","message","stack","type","safeStringify","consoleCfg","resolveConsole","method","orig","level","args","consoleEvent","c","opt","errArg","a","formatArg","arg","value","Dedupe","windowMs","fingerprint","now","last","k","t","RateLimiter","maxPerMin","elapsed","VERSION","Transport","dsn","opts","sep","useBeacon","batch","body","res","room","delay","events","cyrb53","str","seed","h1","h2","ch","topFrames","n","makeFingerprint","parts","normalized","m","u","scrubUrl","url","sessionId","uuid","r","getSessionId","GLOBAL_KEY","bind","originalConsole","isBrowser","Monitor","raw","rate","final","error","user","list","p","hay","denyUrls","allowUrls","match","beacon","resolveEndpoint","parseDsn","endpointOverride","publicKey","projectId","ingestUrl","init","w","existing","client","resolveConfig","getClient","captureError","captureMessage","setUser","flush"],"mappings":"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","file":"index.js","sourcesContent":["import type { EventSource, Level, MonitorConfig } from '../types';\n\n/** A partial event produced by a capture source, before enrichment. */\nexport interface RawEvent {\n level: Level;\n source: EventSource;\n message: string;\n stack?: string;\n type?: string;\n filename?: string;\n lineno?: number;\n colno?: number;\n}\n\ntype CaptureFn = (raw: RawEvent) => void;\n\n/**\n * Installs the global capture sources. Returns an uninstall function that\n * restores everything (used by Monitor.close and for HMR safety).\n */\nexport function installHandlers(config: MonitorConfig, capture: CaptureFn): () => void {\n const cleanups: Array<() => void> = [];\n\n if (config.captureError !== false) {\n const onError = (event: ErrorEvent) => {\n try {\n const target = event.target as (Node & { nodeName?: string }) | null;\n // Resource-load errors (img/script 404) fire on the element, not window.\n if (target && target !== (window as unknown as EventTarget) && target.nodeName) return;\n const err = event.error as Error | undefined;\n capture({\n level: 'error',\n source: 'onerror',\n message: event.message || (err && err.message) || 'Unknown error',\n stack: err && err.stack,\n type: err && err.name,\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno,\n });\n } catch {\n /* never throw from a global handler */\n }\n };\n window.addEventListener('error', onError, true);\n cleanups.push(() => window.removeEventListener('error', onError, true));\n }\n\n if (config.captureUnhandledRejection !== false) {\n const onRejection = (event: PromiseRejectionEvent) => {\n try {\n const reason = event.reason as unknown;\n let message = 'Unhandled Promise Rejection';\n let stack: string | undefined;\n let type: string | undefined;\n if (reason instanceof Error) {\n message = `${message}: ${reason.message}`;\n stack = reason.stack;\n type = reason.name;\n } else if (typeof reason === 'string') {\n message = `${message}: ${reason}`;\n } else if (reason != null) {\n message = `${message}: ${safeStringify(reason)}`;\n }\n capture({ level: 'error', source: 'unhandledrejection', message, stack, type });\n } catch {\n /* noop */\n }\n };\n window.addEventListener('unhandledrejection', onRejection);\n cleanups.push(() => window.removeEventListener('unhandledrejection', onRejection));\n }\n\n const consoleCfg = resolveConsole(config.captureConsole);\n (['error', 'warn'] as const).forEach((method) => {\n if (!consoleCfg[method]) return;\n const orig = console[method];\n const level: Level = method === 'warn' ? 'warning' : 'error';\n console[method] = function patched(...args: unknown[]): void {\n orig.apply(console, args as []);\n try {\n capture(consoleEvent(level, args));\n } catch {\n /* noop */\n }\n };\n cleanups.push(() => {\n console[method] = orig;\n });\n });\n\n return () =>\n cleanups.forEach((c) => {\n try {\n c();\n } catch {\n /* noop */\n }\n });\n}\n\nfunction resolveConsole(opt: MonitorConfig['captureConsole']): { error: boolean; warn: boolean } {\n if (opt === false) return { error: false, warn: false };\n if (opt === undefined || opt === true) return { error: true, warn: true };\n return { error: opt.error !== false, warn: opt.warn !== false };\n}\n\nfunction consoleEvent(level: Level, args: unknown[]): RawEvent {\n let stack: string | undefined;\n let type: string | undefined;\n const errArg = args.find((a) => a instanceof Error) as Error | undefined;\n if (errArg) {\n stack = errArg.stack;\n type = errArg.name;\n }\n const message =\n args.map(formatArg).join(' ').slice(0, 2000) ||\n (level === 'warning' ? 'console.warn' : 'console.error');\n return { level, source: 'console', message, stack, type };\n}\n\nfunction formatArg(arg: unknown): string {\n if (typeof arg === 'string') return arg;\n if (arg instanceof Error) return arg.message;\n return safeStringify(arg);\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n if (typeof value === 'object' && value !== null) return JSON.stringify(value);\n return String(value);\n } catch {\n return Object.prototype.toString.call(value);\n }\n}\n","/** Suppresses identical events seen within a sliding time window. */\nexport class Dedupe {\n private seen = new Map<string, number>();\n\n constructor(private windowMs: number) {}\n\n shouldSend(fingerprint: string, now: number): boolean {\n const last = this.seen.get(fingerprint);\n if (last !== undefined && now - last < this.windowMs) return false;\n\n this.seen.set(fingerprint, now);\n\n if (this.seen.size > 200) {\n for (const [k, t] of this.seen) {\n if (now - t > this.windowMs) this.seen.delete(k);\n }\n }\n return true;\n }\n}\n\n/** Token-bucket limiter so a misbehaving page can't flood the backend. */\nexport class RateLimiter {\n private tokens: number;\n private last: number;\n\n constructor(private maxPerMin: number) {\n this.tokens = maxPerMin;\n this.last = Date.now();\n }\n\n allow(now: number): boolean {\n const elapsed = now - this.last;\n this.last = now;\n this.tokens = Math.min(this.maxPerMin, this.tokens + (elapsed / 60000) * this.maxPerMin);\n if (this.tokens >= 1) {\n this.tokens -= 1;\n return true;\n }\n return false;\n }\n}\n","export const VERSION = '0.1.0';\n","import type { MonitoredEvent } from '../types';\nimport type { ParsedDsn } from '../dsn';\nimport { VERSION } from '../version';\n\ninterface TransportOpts {\n flushInterval: number;\n maxBatchSize: number;\n maxQueueSize: number;\n}\n\n/**\n * Buffers events and ships them in batches. Uses fetch(keepalive) while the\n * page is alive and navigator.sendBeacon on page hide so the last batch is\n * never lost. Failed batches are retried with capped exponential backoff.\n */\nexport class Transport {\n private queue: MonitoredEvent[] = [];\n private timer: ReturnType<typeof setTimeout> | null = null;\n private sending = false;\n private failures = 0;\n private readonly url: string;\n\n constructor(private dsn: ParsedDsn, private opts: TransportOpts) {\n const sep = dsn.ingestUrl.indexOf('?') === -1 ? '?' : '&';\n // Auth via query params (not headers) and a default text/plain body keep\n // this a CORS \"simple request\" — no preflight OPTIONS round-trip, and\n // sendBeacon (which can't set headers) uses the same URL.\n this.url =\n `${dsn.ingestUrl}${sep}key=${encodeURIComponent(dsn.publicKey)}` +\n `&project=${encodeURIComponent(dsn.projectId)}`;\n }\n\n add(event: MonitoredEvent): void {\n if (this.queue.length >= this.opts.maxQueueSize) this.queue.shift();\n this.queue.push(event);\n if (this.queue.length >= this.opts.maxBatchSize) this.flush();\n else this.schedule();\n }\n\n private schedule(): void {\n if (this.timer != null) return;\n this.timer = setTimeout(() => {\n this.timer = null;\n this.flush();\n }, this.opts.flushInterval);\n }\n\n flush(useBeacon = false): void {\n if (this.timer != null) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.queue.length === 0) return;\n if (this.sending && !useBeacon) return;\n\n const batch = this.queue.splice(0, this.opts.maxBatchSize);\n const body = JSON.stringify(this.envelope(batch));\n\n if (useBeacon && typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {\n try {\n const ok = navigator.sendBeacon(this.url, new Blob([body], { type: 'text/plain;charset=UTF-8' }));\n if (!ok) this.queue.unshift(...batch);\n } catch {\n this.queue.unshift(...batch);\n }\n return;\n }\n\n if (typeof fetch !== 'function') return;\n\n this.sending = true;\n // No custom headers + a string body (Content-Type defaults to text/plain)\n // => CORS-safelisted simple request => no preflight.\n fetch(this.url, {\n method: 'POST',\n body,\n keepalive: true,\n mode: 'cors',\n credentials: 'omit',\n })\n .then((res) => {\n this.sending = false;\n if (res.status >= 500) this.requeue(batch);\n else this.failures = 0;\n })\n .catch(() => {\n this.sending = false;\n this.requeue(batch);\n });\n }\n\n private requeue(batch: MonitoredEvent[]): void {\n this.failures++;\n if (this.failures > 5) {\n this.failures = 0;\n return; // give up on this batch to avoid an infinite retry loop\n }\n const room = this.opts.maxQueueSize - this.queue.length;\n if (room > 0) this.queue.unshift(...batch.slice(-room));\n const delay = Math.min(30000, 1000 * Math.pow(2, this.failures));\n setTimeout(() => this.flush(), delay);\n }\n\n private envelope(events: MonitoredEvent[]) {\n return {\n sdk: { name: '@accelerup-llc/web-monitor', version: VERSION },\n project_id: this.dsn.projectId,\n sent_at: Date.now(),\n events,\n };\n }\n}\n","/**\n * cyrb53 — a fast, well-distributed non-cryptographic hash. We only need it\n * client-side for de-duplication / grouping; the backend computes the\n * authoritative SHA-256 fingerprint. Tiny and dependency-free.\n */\nexport function cyrb53(str: string, seed = 0): string {\n let h1 = 0xdeadbeef ^ seed;\n let h2 = 0x41c6ce57 ^ seed;\n for (let i = 0; i < str.length; i++) {\n const ch = str.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString(16).padStart(13, '0');\n}\n\n/** Keep the top N stack frames for stable grouping. */\nexport function topFrames(stack?: string, n = 3): string {\n if (!stack) return '';\n return stack.split('\\n').slice(0, n + 1).join('\\n');\n}\n\n/**\n * Normalizes volatile bits (line/col numbers, addresses, long ids, urls) so\n * that the \"same\" error groups together regardless of run-to-run noise.\n */\nexport function makeFingerprint(parts: Array<string | undefined>): string {\n const normalized = parts\n .filter(Boolean)\n .join('\\n')\n .replace(/:\\d+:\\d+/g, '')\n .replace(/0x[0-9a-fA-F]+/g, '0x')\n .replace(/\\b\\d{4,}\\b/g, 'N')\n .replace(/https?:\\/\\/[^\\s)]+/g, (m) => {\n try {\n const u = new URL(m);\n return u.origin + u.pathname;\n } catch {\n return m;\n }\n });\n return cyrb53(normalized);\n}\n","/**\n * Strips query string and hash from a URL to avoid leaking tokens / PII that\n * commonly live in query params. Only origin + pathname is kept.\n */\nexport function scrubUrl(url: string): string {\n if (!url) return '';\n try {\n const u = new URL(url);\n return u.origin + u.pathname;\n } catch {\n return url.split('?')[0].split('#')[0];\n }\n}\n","let sessionId: string | null = null;\n\nexport function uuid(): string {\n try {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n } catch {\n /* fall through to manual */\n }\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n/** Stable id for the current page session (memory-only, no storage). */\nexport function getSessionId(): string {\n if (!sessionId) sessionId = uuid();\n return sessionId;\n}\n","export const GLOBAL_KEY = '__ACCELERUP_WEB_MONITOR__';\n\nfunction bind(method: 'log' | 'warn' | 'error'): (...args: unknown[]) => void {\n if (typeof console !== 'undefined' && typeof console[method] === 'function') {\n return console[method].bind(console);\n }\n return () => {\n /* noop */\n };\n}\n\n/**\n * References to the real console methods, captured at module load — i.e.\n * BEFORE we patch console. All internal logging must go through these so the\n * SDK never feeds its own output back into the capture pipeline.\n */\nexport const originalConsole = {\n log: bind('log'),\n warn: bind('warn'),\n error: bind('error'),\n};\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n","import type { Level, MonitorConfig, MonitoredEvent, UserContext } from '../types';\nimport type { ParsedDsn } from '../dsn';\nimport type { RawEvent } from './handlers';\nimport { installHandlers } from './handlers';\nimport { Dedupe, RateLimiter } from './dedup';\nimport { Transport } from '../transport/transport';\nimport { makeFingerprint, topFrames } from './fingerprint';\nimport { scrubUrl } from './scrub';\nimport { getSessionId, uuid } from './session';\nimport { isBrowser, originalConsole } from '../utils';\n\nexport interface ResolvedConfig extends MonitorConfig {\n sampleRate: number;\n warningSampleRate: number;\n maxStackChars: number;\n dedupeWindow: number;\n maxEventsPerMinute: number;\n flushInterval: number;\n maxBatchSize: number;\n maxQueueSize: number;\n}\n\nexport class Monitor {\n private readonly transport: Transport;\n private readonly dedupe: Dedupe;\n private readonly rate: RateLimiter;\n private uninstall?: () => void;\n private inCapture = false;\n\n constructor(private config: ResolvedConfig, private dsn: ParsedDsn) {\n this.transport = new Transport(dsn, {\n flushInterval: config.flushInterval,\n maxBatchSize: config.maxBatchSize,\n maxQueueSize: config.maxQueueSize,\n });\n this.dedupe = new Dedupe(config.dedupeWindow);\n this.rate = new RateLimiter(config.maxEventsPerMinute);\n }\n\n start(): void {\n if (this.uninstall) return;\n this.uninstall = installHandlers(this.config, (raw) => this.capture(raw));\n this.installLifecycle();\n if (this.config.debug) {\n originalConsole.log('[accelerup] monitor started', { release: this.config.release });\n }\n }\n\n /** The single funnel every capture source flows through. Never throws. */\n capture(raw: RawEvent): void {\n if (this.inCapture) return; // re-entrancy guard against feedback loops\n this.inCapture = true;\n try {\n if (!raw.message) return;\n // Never report our own ingest traffic.\n if (raw.stack && raw.stack.indexOf(this.dsn.ingestUrl) !== -1) return;\n if (this.isIgnored(raw.message)) return;\n\n const url = scrubUrl(typeof location !== 'undefined' ? location.href : '');\n if (!this.passUrlFilters(raw.stack, url)) return;\n\n const rate = raw.level === 'warning' ? this.config.warningSampleRate : this.config.sampleRate;\n if (rate < 1 && Math.random() > rate) return;\n\n const stack = raw.stack ? raw.stack.slice(0, this.config.maxStackChars) : undefined;\n const fingerprint = makeFingerprint([raw.type, raw.message, topFrames(stack)]);\n\n const now = Date.now();\n if (!this.dedupe.shouldSend(fingerprint, now)) return;\n if (!this.rate.allow(now)) return;\n\n const event: MonitoredEvent = {\n event_id: uuid(),\n level: raw.level,\n message: raw.message.slice(0, 2000),\n type: raw.type,\n stack,\n source: raw.source,\n fingerprint,\n url,\n filename: raw.filename,\n lineno: raw.lineno,\n colno: raw.colno,\n release: this.config.release,\n environment: this.config.environment,\n session_id: getSessionId(),\n user: this.config.user,\n user_agent: typeof navigator !== 'undefined' ? navigator.userAgent : '',\n timestamp: now,\n tags: this.config.tags,\n };\n\n let final: MonitoredEvent | null = event;\n if (this.config.beforeSend) {\n try {\n final = this.config.beforeSend(event);\n } catch {\n final = event;\n }\n }\n if (!final) return;\n\n this.transport.add(final);\n if (this.config.debug) originalConsole.log('[accelerup] captured', final.level, final.message);\n } catch {\n /* swallow — capture must never break the host app */\n } finally {\n this.inCapture = false;\n }\n }\n\n captureException(\n error: unknown,\n opts?: { level?: Level; source?: RawEvent['source']; tags?: Record<string, string> },\n ): void {\n let message = 'Error';\n let stack: string | undefined;\n let type: string | undefined;\n if (error instanceof Error) {\n message = error.message;\n stack = error.stack;\n type = error.name;\n } else if (typeof error === 'string') {\n message = error;\n } else if (error != null) {\n try {\n message = JSON.stringify(error);\n } catch {\n message = String(error);\n }\n }\n this.capture({\n level: opts?.level ?? 'error',\n source: opts?.source ?? 'manual',\n message,\n stack,\n type,\n });\n }\n\n captureMessage(message: string, level: Level = 'warning'): void {\n this.capture({ level, source: 'manual', message });\n }\n\n setUser(user: UserContext | undefined): void {\n this.config.user = user;\n }\n\n flush(): void {\n this.transport.flush();\n }\n\n close(): void {\n this.transport.flush(true);\n if (this.uninstall) {\n this.uninstall();\n this.uninstall = undefined;\n }\n }\n\n private isIgnored(message: string): boolean {\n const list = this.config.ignoreErrors;\n if (!list) return false;\n return list.some((p) => (typeof p === 'string' ? message.indexOf(p) !== -1 : p.test(message)));\n }\n\n private passUrlFilters(stack: string | undefined, url: string): boolean {\n const hay = `${stack || ''} ${url}`;\n const { denyUrls, allowUrls } = this.config;\n if (denyUrls && denyUrls.some((p) => match(p, hay))) return false;\n if (allowUrls && allowUrls.length > 0 && !allowUrls.some((p) => match(p, hay))) return false;\n return true;\n }\n\n private installLifecycle(): void {\n if (!isBrowser()) return;\n const beacon = () => this.transport.flush(true);\n window.addEventListener('pagehide', beacon);\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'hidden') this.transport.flush(true);\n });\n }\n}\n\nfunction match(p: string | RegExp, value: string): boolean {\n return typeof p === 'string' ? value.indexOf(p) !== -1 : p.test(value);\n}\n","import type { MonitorConfig } from './types';\n\nexport interface ParsedDsn {\n publicKey: string;\n projectId: string;\n ingestUrl: string;\n}\n\n/**\n * Resolves the ingest target from config. Prefers the explicit\n * `ingestUrl` + `key` pair (env-friendly); falls back to a `dsn` string.\n */\nexport function resolveEndpoint(config: MonitorConfig): ParsedDsn | null {\n if (config.ingestUrl && config.key) {\n return {\n publicKey: config.key,\n projectId: config.project || '',\n ingestUrl: config.ingestUrl.replace(/\\/+$/, ''),\n };\n }\n if (config.dsn) {\n return parseDsn(config.dsn, config.endpoint);\n }\n return null;\n}\n\n/**\n * Parses a DSN of the form `https://PUBLIC_KEY@host[:port]/PROJECT_ID`.\n * Falls back to `?key=` / `?project=` query params when present.\n */\nexport function parseDsn(dsn: string, endpointOverride?: string): ParsedDsn | null {\n try {\n const u = new URL(dsn);\n const publicKey = u.username || u.searchParams.get('key') || '';\n const projectId =\n u.pathname.replace(/^\\/+/, '').split('/')[0] ||\n u.searchParams.get('project') ||\n '';\n\n if (!publicKey || !projectId) return null;\n\n const ingestUrl = endpointOverride\n ? endpointOverride.replace(/\\/+$/, '')\n : `${u.protocol}//${u.host}/ingest/web-errors`;\n\n return { publicKey, projectId, ingestUrl };\n } catch {\n return null;\n }\n}\n","import type { MonitorConfig } from './types';\nimport type { ResolvedConfig } from './core/client';\nimport { Monitor } from './core/client';\nimport { resolveEndpoint } from './dsn';\nimport { GLOBAL_KEY, isBrowser, originalConsole } from './utils';\nimport { VERSION } from './version';\n\ninterface GlobalRegistry {\n __initialized: boolean;\n client?: Monitor;\n version: string;\n}\n\n/**\n * Initializes the monitor. Safe to call multiple times — the second and later\n * calls return the existing instance (idempotent across HMR, double imports,\n * and App Router + Pages Router both mounting). A no-op on the server (SSR).\n */\nexport function init(config: MonitorConfig): Monitor | undefined {\n if (!isBrowser()) return undefined;\n if (config.enabled === false) return undefined;\n if (!config || (!config.dsn && !(config.ingestUrl && config.key))) {\n originalConsole.warn('[accelerup] init() needs either { ingestUrl, key } or { dsn } — skipping.');\n return undefined;\n }\n\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n const existing = w[GLOBAL_KEY];\n if (existing && existing.__initialized && existing.client) {\n return existing.client;\n }\n\n const dsn = resolveEndpoint(config);\n if (!dsn) {\n originalConsole.warn('[accelerup] invalid config — provide { ingestUrl, key } or a valid dsn');\n return undefined;\n }\n\n const client = new Monitor(resolveConfig(config), dsn);\n w[GLOBAL_KEY] = { __initialized: true, client, version: VERSION };\n client.start();\n return client;\n}\n\nexport function getClient(): Monitor | undefined {\n if (!isBrowser()) return undefined;\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n return w[GLOBAL_KEY]?.client;\n}\n\nfunction resolveConfig(c: MonitorConfig): ResolvedConfig {\n return {\n ...c,\n sampleRate: c.sampleRate ?? 1,\n warningSampleRate: c.warningSampleRate ?? 1,\n maxStackChars: c.maxStackChars ?? 4000,\n dedupeWindow: c.dedupeWindow ?? 5000,\n maxEventsPerMinute: c.maxEventsPerMinute ?? 30,\n flushInterval: c.flushInterval ?? 5000,\n maxBatchSize: c.maxBatchSize ?? 20,\n maxQueueSize: c.maxQueueSize ?? 100,\n };\n}\n","import type { Level, UserContext } from './types';\nimport { getClient } from './init';\n\n/** Manually report an error/exception. No-op if init() hasn't run. */\nexport function captureError(\n error: unknown,\n opts?: { level?: Level; tags?: Record<string, string> },\n): void {\n getClient()?.captureException(error, opts);\n}\n\n/** Manually report a message (defaults to warning level). */\nexport function captureMessage(message: string, level: Level = 'warning'): void {\n getClient()?.captureMessage(message, level);\n}\n\n/** Attach (or clear) the current user context for subsequent events. */\nexport function setUser(user: UserContext | undefined): void {\n getClient()?.setUser(user);\n}\n\n/** Force an immediate flush of the buffered events. */\nexport function flush(): void {\n getClient()?.flush();\n}\n"]}
@@ -0,0 +1,2 @@
1
+ 'use strict';var d=require('react');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var d__namespace=/*#__PURE__*/_interopNamespace(d);var o="__ACCELERUP_WEB_MONITOR__";function t(n){return typeof console<"u"&&typeof console[n]=="function"?console[n].bind(console):()=>{}}({log:t("log"),warn:t("warn"),error:t("error")});function i(){return typeof window<"u"&&typeof document<"u"}function a(){return i()?window[o]?.client:void 0}var s=class extends d__namespace.Component{constructor(){super(...arguments);this.state={error:null};}static getDerivedStateFromError(e){return {error:e}}componentDidCatch(e,r){try{a()?.captureException(e,{source:"react"});}catch{}this.props.onError?.(e,r);}render(){let{error:e}=this.state;if(e){let{fallback:r}=this.props;return typeof r=="function"?r(e):r??null}return this.props.children}};exports.ErrorBoundary=s;//# sourceMappingURL=index.cjs.map
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts","../../src/init.ts","../../src/react/index.tsx"],"names":["GLOBAL_KEY","bind","method","isBrowser","getClient","ErrorBoundary","d","error","info","fallback"],"mappings":"0YAAO,IAAMA,CAAAA,CAAa,4BAE1B,SAASC,CAAAA,CAAKC,CAAAA,CAAgE,CAC5E,OAAI,OAAO,OAAA,CAAY,GAAA,EAAe,OAAO,OAAA,CAAQA,CAAM,CAAA,EAAM,UAAA,CACxD,OAAA,CAAQA,CAAM,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA,CAE9B,IAAM,CAEb,CACF,EAO+B,CAC7B,GAAA,CAAKD,EAAK,KAAK,CAAA,CACf,IAAA,CAAMA,CAAAA,CAAK,MAAM,CAAA,CACjB,KAAA,CAAOA,CAAAA,CAAK,OAAO,CACrB,GAEO,SAASE,CAAAA,EAAqB,CACnC,OAAO,OAAO,MAAA,CAAW,GAAA,EAAe,OAAO,QAAA,CAAa,GAC9D,CCoBO,SAASC,CAAAA,EAAiC,CAC/C,OAAKD,CAAAA,GACK,MAAA,CACDH,CAAU,CAAA,EAAG,MAAA,CAFJ,MAGpB,CC5BO,IAAMK,CAAAA,CAAN,cAAkCC,sBAAqC,CAAvE,WAAA,EAAA,CAAA,KAAA,CAAA,GAAA,SAAA,CAAA,CACL,IAAA,CAAA,KAAA,CAAe,CAAE,KAAA,CAAO,IAAK,EAAA,CAE7B,OAAO,yBAAyBC,CAAAA,CAAqB,CACnD,OAAO,CAAE,KAAA,CAAAA,CAAM,CACjB,CAEA,kBAAkBA,CAAAA,CAAcC,CAAAA,CAA6B,CAC3D,GAAI,CACFJ,CAAAA,EAAU,EAAG,gBAAA,CAAiBG,EAAO,CAAE,MAAA,CAAQ,OAAQ,CAAC,EAC1D,CAAA,KAAQ,CAER,CACA,IAAA,CAAK,MAAM,OAAA,GAAUA,CAAAA,CAAOC,CAAI,EAClC,CAEA,MAAA,EAA0B,CACxB,GAAM,CAAE,KAAA,CAAAD,CAAM,CAAA,CAAI,IAAA,CAAK,MACvB,GAAIA,CAAAA,CAAO,CACT,GAAM,CAAE,QAAA,CAAAE,CAAS,CAAA,CAAI,IAAA,CAAK,KAAA,CAC1B,OAAO,OAAOA,CAAAA,EAAa,WAAaA,CAAAA,CAASF,CAAK,CAAA,CAAKE,CAAAA,EAAY,IACzE,CACA,OAAO,IAAA,CAAK,KAAA,CAAM,QACpB,CACF","file":"index.cjs","sourcesContent":["export const GLOBAL_KEY = '__ACCELERUP_WEB_MONITOR__';\n\nfunction bind(method: 'log' | 'warn' | 'error'): (...args: unknown[]) => void {\n if (typeof console !== 'undefined' && typeof console[method] === 'function') {\n return console[method].bind(console);\n }\n return () => {\n /* noop */\n };\n}\n\n/**\n * References to the real console methods, captured at module load — i.e.\n * BEFORE we patch console. All internal logging must go through these so the\n * SDK never feeds its own output back into the capture pipeline.\n */\nexport const originalConsole = {\n log: bind('log'),\n warn: bind('warn'),\n error: bind('error'),\n};\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n","import type { MonitorConfig } from './types';\nimport type { ResolvedConfig } from './core/client';\nimport { Monitor } from './core/client';\nimport { resolveEndpoint } from './dsn';\nimport { GLOBAL_KEY, isBrowser, originalConsole } from './utils';\nimport { VERSION } from './version';\n\ninterface GlobalRegistry {\n __initialized: boolean;\n client?: Monitor;\n version: string;\n}\n\n/**\n * Initializes the monitor. Safe to call multiple times — the second and later\n * calls return the existing instance (idempotent across HMR, double imports,\n * and App Router + Pages Router both mounting). A no-op on the server (SSR).\n */\nexport function init(config: MonitorConfig): Monitor | undefined {\n if (!isBrowser()) return undefined;\n if (config.enabled === false) return undefined;\n if (!config || (!config.dsn && !(config.ingestUrl && config.key))) {\n originalConsole.warn('[accelerup] init() needs either { ingestUrl, key } or { dsn } — skipping.');\n return undefined;\n }\n\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n const existing = w[GLOBAL_KEY];\n if (existing && existing.__initialized && existing.client) {\n return existing.client;\n }\n\n const dsn = resolveEndpoint(config);\n if (!dsn) {\n originalConsole.warn('[accelerup] invalid config — provide { ingestUrl, key } or a valid dsn');\n return undefined;\n }\n\n const client = new Monitor(resolveConfig(config), dsn);\n w[GLOBAL_KEY] = { __initialized: true, client, version: VERSION };\n client.start();\n return client;\n}\n\nexport function getClient(): Monitor | undefined {\n if (!isBrowser()) return undefined;\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n return w[GLOBAL_KEY]?.client;\n}\n\nfunction resolveConfig(c: MonitorConfig): ResolvedConfig {\n return {\n ...c,\n sampleRate: c.sampleRate ?? 1,\n warningSampleRate: c.warningSampleRate ?? 1,\n maxStackChars: c.maxStackChars ?? 4000,\n dedupeWindow: c.dedupeWindow ?? 5000,\n maxEventsPerMinute: c.maxEventsPerMinute ?? 30,\n flushInterval: c.flushInterval ?? 5000,\n maxBatchSize: c.maxBatchSize ?? 20,\n maxQueueSize: c.maxQueueSize ?? 100,\n };\n}\n","import * as React from 'react';\nimport { getClient } from '../init';\n\nexport interface ErrorBoundaryProps {\n children: React.ReactNode;\n /** Rendered when a child throws. Receives the error if given a function. */\n fallback?: React.ReactNode | ((error: Error) => React.ReactNode);\n /** Called in addition to reporting the error to the monitor. */\n onError?: (error: Error, info: React.ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * React error boundary that forwards render-time crashes to the monitor.\n * Works in both App Router (`'use client'`) and Pages Router. Reporting is a\n * no-op if init() hasn't run, so it's safe to mount anywhere.\n */\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: React.ErrorInfo): void {\n try {\n getClient()?.captureException(error, { source: 'react' });\n } catch {\n /* noop */\n }\n this.props.onError?.(error, info);\n }\n\n render(): React.ReactNode {\n const { error } = this.state;\n if (error) {\n const { fallback } = this.props;\n return typeof fallback === 'function' ? fallback(error) : (fallback ?? null);\n }\n return this.props.children;\n }\n}\n"]}
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+
3
+ interface ErrorBoundaryProps {
4
+ children: React.ReactNode;
5
+ /** Rendered when a child throws. Receives the error if given a function. */
6
+ fallback?: React.ReactNode | ((error: Error) => React.ReactNode);
7
+ /** Called in addition to reporting the error to the monitor. */
8
+ onError?: (error: Error, info: React.ErrorInfo) => void;
9
+ }
10
+ interface State {
11
+ error: Error | null;
12
+ }
13
+ /**
14
+ * React error boundary that forwards render-time crashes to the monitor.
15
+ * Works in both App Router (`'use client'`) and Pages Router. Reporting is a
16
+ * no-op if init() hasn't run, so it's safe to mount anywhere.
17
+ */
18
+ declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
19
+ state: State;
20
+ static getDerivedStateFromError(error: Error): State;
21
+ componentDidCatch(error: Error, info: React.ErrorInfo): void;
22
+ render(): React.ReactNode;
23
+ }
24
+
25
+ export { ErrorBoundary, type ErrorBoundaryProps };
@@ -0,0 +1,25 @@
1
+ import * as React from 'react';
2
+
3
+ interface ErrorBoundaryProps {
4
+ children: React.ReactNode;
5
+ /** Rendered when a child throws. Receives the error if given a function. */
6
+ fallback?: React.ReactNode | ((error: Error) => React.ReactNode);
7
+ /** Called in addition to reporting the error to the monitor. */
8
+ onError?: (error: Error, info: React.ErrorInfo) => void;
9
+ }
10
+ interface State {
11
+ error: Error | null;
12
+ }
13
+ /**
14
+ * React error boundary that forwards render-time crashes to the monitor.
15
+ * Works in both App Router (`'use client'`) and Pages Router. Reporting is a
16
+ * no-op if init() hasn't run, so it's safe to mount anywhere.
17
+ */
18
+ declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {
19
+ state: State;
20
+ static getDerivedStateFromError(error: Error): State;
21
+ componentDidCatch(error: Error, info: React.ErrorInfo): void;
22
+ render(): React.ReactNode;
23
+ }
24
+
25
+ export { ErrorBoundary, type ErrorBoundaryProps };
@@ -0,0 +1,2 @@
1
+ import*as d from'react';var o="__ACCELERUP_WEB_MONITOR__";function t(n){return typeof console<"u"&&typeof console[n]=="function"?console[n].bind(console):()=>{}}({log:t("log"),warn:t("warn"),error:t("error")});function i(){return typeof window<"u"&&typeof document<"u"}function a(){return i()?window[o]?.client:void 0}var s=class extends d.Component{constructor(){super(...arguments);this.state={error:null};}static getDerivedStateFromError(e){return {error:e}}componentDidCatch(e,r){try{a()?.captureException(e,{source:"react"});}catch{}this.props.onError?.(e,r);}render(){let{error:e}=this.state;if(e){let{fallback:r}=this.props;return typeof r=="function"?r(e):r??null}return this.props.children}};export{s as ErrorBoundary};//# sourceMappingURL=index.js.map
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/utils.ts","../../src/init.ts","../../src/react/index.tsx"],"names":["GLOBAL_KEY","bind","method","isBrowser","getClient","ErrorBoundary","error","info","fallback"],"mappings":"wBAAO,IAAMA,CAAAA,CAAa,4BAE1B,SAASC,CAAAA,CAAKC,CAAAA,CAAgE,CAC5E,OAAI,OAAO,OAAA,CAAY,GAAA,EAAe,OAAO,OAAA,CAAQA,CAAM,CAAA,EAAM,UAAA,CACxD,OAAA,CAAQA,CAAM,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA,CAE9B,IAAM,CAEb,CACF,EAO+B,CAC7B,GAAA,CAAKD,EAAK,KAAK,CAAA,CACf,IAAA,CAAMA,CAAAA,CAAK,MAAM,CAAA,CACjB,KAAA,CAAOA,CAAAA,CAAK,OAAO,CACrB,GAEO,SAASE,CAAAA,EAAqB,CACnC,OAAO,OAAO,MAAA,CAAW,GAAA,EAAe,OAAO,QAAA,CAAa,GAC9D,CCoBO,SAASC,CAAAA,EAAiC,CAC/C,OAAKD,CAAAA,GACK,MAAA,CACDH,CAAU,CAAA,EAAG,MAAA,CAFJ,MAGpB,CC5BO,IAAMK,CAAAA,CAAN,cAAkC,WAAqC,CAAvE,WAAA,EAAA,CAAA,KAAA,CAAA,GAAA,SAAA,CAAA,CACL,IAAA,CAAA,KAAA,CAAe,CAAE,KAAA,CAAO,IAAK,EAAA,CAE7B,OAAO,yBAAyBC,CAAAA,CAAqB,CACnD,OAAO,CAAE,KAAA,CAAAA,CAAM,CACjB,CAEA,kBAAkBA,CAAAA,CAAcC,CAAAA,CAA6B,CAC3D,GAAI,CACFH,CAAAA,EAAU,EAAG,gBAAA,CAAiBE,EAAO,CAAE,MAAA,CAAQ,OAAQ,CAAC,EAC1D,CAAA,KAAQ,CAER,CACA,IAAA,CAAK,MAAM,OAAA,GAAUA,CAAAA,CAAOC,CAAI,EAClC,CAEA,MAAA,EAA0B,CACxB,GAAM,CAAE,KAAA,CAAAD,CAAM,CAAA,CAAI,IAAA,CAAK,MACvB,GAAIA,CAAAA,CAAO,CACT,GAAM,CAAE,QAAA,CAAAE,CAAS,CAAA,CAAI,IAAA,CAAK,KAAA,CAC1B,OAAO,OAAOA,CAAAA,EAAa,WAAaA,CAAAA,CAASF,CAAK,CAAA,CAAKE,CAAAA,EAAY,IACzE,CACA,OAAO,IAAA,CAAK,KAAA,CAAM,QACpB,CACF","file":"index.js","sourcesContent":["export const GLOBAL_KEY = '__ACCELERUP_WEB_MONITOR__';\n\nfunction bind(method: 'log' | 'warn' | 'error'): (...args: unknown[]) => void {\n if (typeof console !== 'undefined' && typeof console[method] === 'function') {\n return console[method].bind(console);\n }\n return () => {\n /* noop */\n };\n}\n\n/**\n * References to the real console methods, captured at module load — i.e.\n * BEFORE we patch console. All internal logging must go through these so the\n * SDK never feeds its own output back into the capture pipeline.\n */\nexport const originalConsole = {\n log: bind('log'),\n warn: bind('warn'),\n error: bind('error'),\n};\n\nexport function isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n","import type { MonitorConfig } from './types';\nimport type { ResolvedConfig } from './core/client';\nimport { Monitor } from './core/client';\nimport { resolveEndpoint } from './dsn';\nimport { GLOBAL_KEY, isBrowser, originalConsole } from './utils';\nimport { VERSION } from './version';\n\ninterface GlobalRegistry {\n __initialized: boolean;\n client?: Monitor;\n version: string;\n}\n\n/**\n * Initializes the monitor. Safe to call multiple times — the second and later\n * calls return the existing instance (idempotent across HMR, double imports,\n * and App Router + Pages Router both mounting). A no-op on the server (SSR).\n */\nexport function init(config: MonitorConfig): Monitor | undefined {\n if (!isBrowser()) return undefined;\n if (config.enabled === false) return undefined;\n if (!config || (!config.dsn && !(config.ingestUrl && config.key))) {\n originalConsole.warn('[accelerup] init() needs either { ingestUrl, key } or { dsn } — skipping.');\n return undefined;\n }\n\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n const existing = w[GLOBAL_KEY];\n if (existing && existing.__initialized && existing.client) {\n return existing.client;\n }\n\n const dsn = resolveEndpoint(config);\n if (!dsn) {\n originalConsole.warn('[accelerup] invalid config — provide { ingestUrl, key } or a valid dsn');\n return undefined;\n }\n\n const client = new Monitor(resolveConfig(config), dsn);\n w[GLOBAL_KEY] = { __initialized: true, client, version: VERSION };\n client.start();\n return client;\n}\n\nexport function getClient(): Monitor | undefined {\n if (!isBrowser()) return undefined;\n const w = window as unknown as Record<string, GlobalRegistry | undefined>;\n return w[GLOBAL_KEY]?.client;\n}\n\nfunction resolveConfig(c: MonitorConfig): ResolvedConfig {\n return {\n ...c,\n sampleRate: c.sampleRate ?? 1,\n warningSampleRate: c.warningSampleRate ?? 1,\n maxStackChars: c.maxStackChars ?? 4000,\n dedupeWindow: c.dedupeWindow ?? 5000,\n maxEventsPerMinute: c.maxEventsPerMinute ?? 30,\n flushInterval: c.flushInterval ?? 5000,\n maxBatchSize: c.maxBatchSize ?? 20,\n maxQueueSize: c.maxQueueSize ?? 100,\n };\n}\n","import * as React from 'react';\nimport { getClient } from '../init';\n\nexport interface ErrorBoundaryProps {\n children: React.ReactNode;\n /** Rendered when a child throws. Receives the error if given a function. */\n fallback?: React.ReactNode | ((error: Error) => React.ReactNode);\n /** Called in addition to reporting the error to the monitor. */\n onError?: (error: Error, info: React.ErrorInfo) => void;\n}\n\ninterface State {\n error: Error | null;\n}\n\n/**\n * React error boundary that forwards render-time crashes to the monitor.\n * Works in both App Router (`'use client'`) and Pages Router. Reporting is a\n * no-op if init() hasn't run, so it's safe to mount anywhere.\n */\nexport class ErrorBoundary extends React.Component<ErrorBoundaryProps, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: React.ErrorInfo): void {\n try {\n getClient()?.captureException(error, { source: 'react' });\n } catch {\n /* noop */\n }\n this.props.onError?.(error, info);\n }\n\n render(): React.ReactNode {\n const { error } = this.state;\n if (error) {\n const { fallback } = this.props;\n return typeof fallback === 'function' ? fallback(error) : (fallback ?? null);\n }\n return this.props.children;\n }\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@accelerup-llc/web-monitor",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight, zero-dependency error & warning monitoring SDK for Next.js (App Router + Pages Router). Init once, capture everything.",
5
+ "type": "module",
6
+ "sideEffects": false,
7
+ "main": "./dist/index.cjs",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "types": "./dist/index.d.ts",
18
+ "import": "./dist/index.js",
19
+ "require": "./dist/index.cjs"
20
+ },
21
+ "./react": {
22
+ "types": "./dist/react/index.d.ts",
23
+ "import": "./dist/react/index.js",
24
+ "require": "./dist/react/index.cjs"
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "tsup",
29
+ "dev": "tsup --watch",
30
+ "typecheck": "tsc --noEmit",
31
+ "prepublishOnly": "npm run build"
32
+ },
33
+ "keywords": [
34
+ "error-tracking",
35
+ "error-monitoring",
36
+ "warnings",
37
+ "nextjs",
38
+ "app-router",
39
+ "pages-router",
40
+ "observability",
41
+ "accelerup"
42
+ ],
43
+ "author": "AccelerUp",
44
+ "license": "MIT",
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "peerDependencies": {
49
+ "react": ">=17.0.0"
50
+ },
51
+ "peerDependenciesMeta": {
52
+ "react": {
53
+ "optional": true
54
+ }
55
+ },
56
+ "devDependencies": {
57
+ "@types/react": "^18.3.3",
58
+ "react": "^18.3.1",
59
+ "tsup": "^8.3.5",
60
+ "typescript": "^5.5.4"
61
+ },
62
+ "engines": {
63
+ "node": ">=18"
64
+ }
65
+ }