error-monitor-web 1.0.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) 2025 Error Monitor SDK
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,323 @@
1
+ # error-monitor-web
2
+
3
+ Web error monitoring SDK - Browser-specific error tracking capabilities built on top of error-monitor-core.
4
+
5
+ ## Features
6
+
7
+ - 🌐 **Browser Error Capture**: Automatically captures JavaScript errors, Promise rejections, network errors, and resource loading errors
8
+ - 🖥️ **Blank Screen Detection**: Intelligent detection of white screen issues
9
+ - 📡 **Request Interception**: Built-in fetch and XMLHttpRequest interception
10
+ - 🎨 **Context Collection**: Automatic collection of browser context information (user agent, URL, viewport)
11
+ - 🔗 **Easy Integration**: Simple setup with automatic browser API hooking
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install error-monitor-web
17
+ # or
18
+ pnpm install error-monitor-web
19
+ # or
20
+ yarn add error-monitor-web
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { ErrorMonitorWeb } from 'error-monitor-web'
27
+
28
+ // Initialize the monitor
29
+ const monitor = new ErrorMonitorWeb({
30
+ appId: 'your-app-id',
31
+ dsn: 'https://your-error-server.com/collect',
32
+ enabled: true,
33
+
34
+ // Auto-capture options (all enabled by default)
35
+ autoCapture: {
36
+ js: true, // JavaScript errors
37
+ promise: true, // Promise rejections
38
+ network: true, // Network errors (fetch/XHR)
39
+ resource: true // Resource loading errors
40
+ }
41
+ })
42
+
43
+ // Start monitoring
44
+ monitor.init()
45
+
46
+ // The monitor will now automatically capture:
47
+ // - Unhandled JavaScript errors
48
+ // - Unhandled Promise rejections
49
+ // - Failed fetch requests
50
+ // - Failed XMLHttpRequests
51
+ // - Failed resource loading (images, scripts, stylesheets, etc.)
52
+ ```
53
+
54
+ ## Configuration
55
+
56
+ All options from `error-monitor-core` plus web-specific options:
57
+
58
+ ```typescript
59
+ interface WebConfig extends Config {
60
+ // Auto-capture switches
61
+ autoCapture?: {
62
+ js?: boolean // JavaScript errors (default: true)
63
+ promise?: boolean // Promise rejections (default: true)
64
+ network?: boolean // Network errors (default: true)
65
+ resource?: boolean // Resource loading errors (default: true)
66
+ }
67
+
68
+ // Blank screen detection
69
+ blankScreenDetection?: {
70
+ enabled?: boolean // Enable blank screen detection (default: false)
71
+ detectionDelay?: number // Delay before first check (ms, default: 3000)
72
+ minElements?: number // Minimum DOM elements to consider not blank (default: 10)
73
+ checkInterval?: number // Check interval (ms, default: 1000)
74
+ maxChecks?: number // Maximum number of checks (default: 5)
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## Automatic Error Capture
80
+
81
+ ### JavaScript Errors
82
+
83
+ ```typescript
84
+ // Automatically captured when enabled
85
+ // Error includes:
86
+ // - Error message and stack trace
87
+ // - File name, line number, column number
88
+ // - Browser context (user agent, URL, viewport)
89
+ ```
90
+
91
+ ### Promise Rejections
92
+
93
+ ```typescript
94
+ // Automatically captured when enabled
95
+ // Captures unhandled promise rejections
96
+ // Includes rejection reason and stack trace
97
+ ```
98
+
99
+ ### Network Errors
100
+
101
+ ```typescript
102
+ // Fetch errors are automatically intercepted
103
+ fetch('https://api.example.com/data')
104
+ .then(res => res.json())
105
+ .catch(error => {
106
+ // Error is captured automatically
107
+ })
108
+
109
+ // XMLHttpRequest errors are also intercepted
110
+ const xhr = new XMLHttpRequest()
111
+ xhr.open('GET', 'https://api.example.com/data')
112
+ xhr.send()
113
+ // If this fails, the error is captured
114
+ ```
115
+
116
+ ### Resource Loading Errors
117
+
118
+ ```typescript
119
+ // Resource loading failures are captured
120
+ // <img src="missing-image.png" />
121
+ // If this fails to load, the error is captured
122
+ ```
123
+
124
+ ## Manual Error Capture
125
+
126
+ ```typescript
127
+ // Capture errors manually
128
+ try {
129
+ // Your code
130
+ } catch (error) {
131
+ monitor.captureError(error, {
132
+ level: 'error',
133
+ tags: { module: 'checkout' },
134
+ extra: { cartId: '12345' }
135
+ })
136
+ }
137
+
138
+ // Capture custom messages
139
+ monitor.captureMessage('Payment failed', 'warning', {
140
+ extra: { reason: 'Insufficient funds', amount: 100 }
141
+ })
142
+ ```
143
+
144
+ ## Blank Screen Detection
145
+
146
+ ```typescript
147
+ const monitor = new ErrorMonitorWeb({
148
+ appId: 'your-app-id',
149
+ dsn: 'https://your-error-server.com/collect',
150
+ blankScreenDetection: {
151
+ enabled: true,
152
+ detectionDelay: 5000, // Start checking after 5 seconds
153
+ minElements: 15, // Need at least 15 DOM elements
154
+ checkInterval: 1000, // Check every second
155
+ maxChecks: 5 // Check 5 times max
156
+ }
157
+ })
158
+
159
+ monitor.init()
160
+
161
+ // Blank screen detection will:
162
+ // - Monitor DOM element count
163
+ // - Check if body has content
164
+ // - Use Performance API for additional metrics
165
+ // - Report blank screen if detected
166
+ ```
167
+
168
+ ## Breadcrumbs
169
+
170
+ Track user actions leading up to errors:
171
+
172
+ ```typescript
173
+ // Add navigation breadcrumbs
174
+ monitor.addBreadcrumb({
175
+ type: 'navigation',
176
+ message: 'User navigated to checkout',
177
+ data: { from: '/cart', to: '/checkout' }
178
+ })
179
+
180
+ // Add user action breadcrumbs
181
+ monitor.addBreadcrumb({
182
+ type: 'user',
183
+ message: 'User clicked submit button',
184
+ data: { buttonId: 'submit-payment' }
185
+ })
186
+
187
+ // Add custom breadcrumbs
188
+ monitor.addBreadcrumb({
189
+ type: 'custom',
190
+ message: 'API call started',
191
+ data: { endpoint: '/api/payment' }
192
+ })
193
+ ```
194
+
195
+ ## User Information
196
+
197
+ ```typescript
198
+ // Set user information
199
+ monitor.setUser({
200
+ id: 'user-123',
201
+ username: 'john_doe',
202
+ email: 'john@example.com',
203
+ plan: 'premium'
204
+ })
205
+
206
+ // User info is included in all error reports
207
+ ```
208
+
209
+ ## Tags
210
+
211
+ ```typescript
212
+ // Add tags to categorize errors
213
+ monitor.setTags({
214
+ environment: 'production',
215
+ version: '1.0.0',
216
+ framework: 'react',
217
+ build: '2024-01-29'
218
+ })
219
+ ```
220
+
221
+ ## Context Information
222
+
223
+ Automatically collected context:
224
+
225
+ ```typescript
226
+ {
227
+ userAgent: string // Browser user agent
228
+ url: string // Current page URL
229
+ viewport: {
230
+ width: number // Viewport width
231
+ height: number // Viewport height
232
+ }
233
+ }
234
+ ```
235
+
236
+ ## Sampling
237
+
238
+ Control error reporting rate:
239
+
240
+ ```typescript
241
+ // Set overall sampling rate (capture 10% of all events)
242
+ monitor.setSampleRate(0.1)
243
+
244
+ // Set error-specific sampling rate
245
+ monitor.setErrorSampleRate(0.5) // Capture 50% of errors
246
+ ```
247
+
248
+ ## Filtering
249
+
250
+ Filter out unwanted errors:
251
+
252
+ ```typescript
253
+ // Filter by error message pattern
254
+ monitor.addFilter(/Script error/i) // Ignore all script errors
255
+ monitor.addFilter(/_追踪/) // Ignore errors containing "_追踪"
256
+
257
+ // Errors matching patterns won't be captured
258
+ ```
259
+
260
+ ## Error Report Format
261
+
262
+ ```typescript
263
+ {
264
+ appId: 'your-app-id',
265
+ timestamp: 1234567890,
266
+ sessionId: 'session-123',
267
+ eventId: 'event-456',
268
+
269
+ type: 'js', // 'js', 'promise', 'network', 'resource', 'custom'
270
+ level: 'error',
271
+ message: 'Uncaught Error: Something went wrong',
272
+ stack: 'Error: Something went wrong\\n at...',
273
+
274
+ context: {
275
+ userAgent: 'Mozilla/5.0...',
276
+ url: 'https://example.com/page',
277
+ viewport: { width: 1920, height: 1080 },
278
+ userId: 'user-123',
279
+ tags: { environment: 'production', version: '1.0.0' }
280
+ },
281
+
282
+ breadcrumbs: [
283
+ {
284
+ timestamp: 1234567880,
285
+ type: 'navigation',
286
+ message: 'User navigated to /checkout',
287
+ data: { from: '/cart' }
288
+ }
289
+ ],
290
+
291
+ extra: {
292
+ customField: 'custom value'
293
+ }
294
+ }
295
+ ```
296
+
297
+ ## Cleanup
298
+
299
+ ```typescript
300
+ // When your app is unmounting or cleaning up
301
+ monitor.destroy()
302
+
303
+ // This will:
304
+ // - Remove all event listeners
305
+ // - Restore original fetch and XMLHttpRequest
306
+ // - Stop blank screen detection
307
+ // - Clear all timers
308
+ ```
309
+
310
+ ## Browser Support
311
+
312
+ - Chrome/Edge: ✅ Latest
313
+ - Firefox: ✅ Latest
314
+ - Safari: ✅ Latest
315
+ - Opera: ✅ Latest
316
+
317
+ ## License
318
+
319
+ MIT
320
+
321
+ ## Support
322
+
323
+ For issues and questions, please visit our GitHub repository.
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});function b(){return`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}function g(){return`${Date.now()}-${Math.random().toString(36).substring(2,15)}`}class p{constructor(e){this.isInitialized=!1,this.breadcrumbs=[],this.maxBreadcrumbs=50,this.plugins=[],this.sessionId=b(),this.config={autoCapture:{js:!0,promise:!0,network:!0,resource:!0,console:!1},filter:{ignoreErrors:[],ignoreUrls:[],minLevel:"info"},report:{delay:1e3,batchSize:10},sampleRate:1,errorSampleRate:1,enabled:!0,debug:!1,...e}}updateConfig(e){this.config={...this.config,...e},this.config.debug&&console.log("[ErrorMonitor] Config updated:",this.config)}enable(){this.config.enabled=!0,console.log("[ErrorMonitor] SDK enabled")}disable(){this.config.enabled=!1,console.log("[ErrorMonitor] SDK disabled")}addFilter(e){this.config.filter||(this.config.filter={}),this.config.filter.ignoreErrors||(this.config.filter.ignoreErrors=[]),this.config.filter.ignoreErrors.push(e)}removeFilter(e){var t;if(!((t=this.config.filter)!=null&&t.ignoreErrors))return;const n=this.config.filter.ignoreErrors.indexOf(e);n>-1&&this.config.filter.ignoreErrors.splice(n,1)}setSampleRate(e){this.config.sampleRate=Math.max(0,Math.min(1,e))}setErrorSampleRate(e){this.config.errorSampleRate=Math.max(0,Math.min(1,e))}init(){if(this.isInitialized){console.warn("[ErrorMonitor] Already initialized");return}this.isInitialized=!0,this.plugins.forEach(e=>{var t;(t=e.setup)==null||t.call(e,this)}),console.log("[ErrorMonitor] Initialized with appId:",this.config.appId)}use(e){var t;this.plugins.push(e),this.isInitialized&&((t=e.setup)==null||t.call(e,this))}capture(e,t){var n,i;if(!this.isInitialized){console.warn("[ErrorMonitor] Not initialized");return}if(this.config.enabled===!1)return;const o=e instanceof Error?{type:"custom",message:e.message,stack:e.stack,context:{}}:e,r={level:"error",tags:{},extra:{},user:{},skipSampling:!1,skipFilter:!1,...t};if(!r.skipFilter&&this.shouldFilter(o)){this.config.debug&&console.log("[ErrorMonitor] Error filtered:",o.message);return}if(!r.skipSampling&&this.config.errorSampleRate!==void 0&&Math.random()>this.config.errorSampleRate)return;let s=o;for(const l of this.plugins){const a=(n=l.beforeCapture)==null?void 0:n.call(l,o);if(a===null)return;a!==void 0&&(s=a)}const c={appId:this.config.appId,timestamp:Date.now(),sessionId:this.sessionId,eventId:g(),type:s.type,level:r.level,message:s.message,stack:s.stack,context:{userAgent:typeof navigator<"u"?navigator.userAgent:"",url:typeof location<"u"?location.href:"",viewport:{width:typeof window<"u"?window.innerWidth:0,height:typeof window<"u"?window.innerHeight:0},userId:r.user.id||this.config.userId,tags:{...this.config.tags,...r.tags}},breadcrumbs:[...this.breadcrumbs],extra:{...s.context,...r.extra}};for(const l of this.plugins){const a=(i=l.afterCapture)==null?void 0:i.call(l,c);a!==void 0&&Object.assign(c,a)}this.report(c)}shouldFilter(e){var t;if(!this.config.filter)return!1;const{ignoreErrors:n,ignoreUrls:i,minLevel:o}=this.config.filter;if(n&&n.length>0){for(const r of n)if(r.test(e.message))return!0}if(i&&i.length>0&&(t=e.context)!=null&&t.url){for(const r of i)if(r.test(e.context.url))return!0}return!1}captureError(e,t){this.capture(e,t)}captureMessage(e,t="info",n){this.capture({type:"custom",message:e,context:{}},{...n,level:t})}report(e){var t;let n=e;for(const i of this.plugins){const o=(t=i.beforeReport)==null?void 0:t.call(i,e);o!==void 0&&(n=o)}this.sendToServer(n)}addBreadcrumb(e){this.breadcrumbs.push({timestamp:e.timestamp||Date.now(),type:e.type,message:e.message,data:e.data}),this.breadcrumbs.length>this.maxBreadcrumbs&&this.breadcrumbs.shift()}generateId(){return g()}setUser(e){this.config.userId=e.id,this.config.tags={...this.config.tags,...e}}sendToServer(e){if(typeof navigator>"u")return;const t=JSON.stringify(e);if(navigator.sendBeacon){const n=new Blob([t],{type:"application/json"});navigator.sendBeacon(this.config.dsn,n);return}typeof fetch<"u"&&fetch(this.config.dsn,{method:"POST",body:t,keepalive:!0,headers:{"Content-Type":"application/json"}}).catch(n=>{console.error("[ErrorMonitor] Failed to send report:",n)})}destroy(){this.plugins.forEach(e=>{var t;(t=e.teardown)==null||t.call(e)}),this.plugins=[],this.breadcrumbs=[],this.isInitialized=!1,console.log("[ErrorMonitor] Destroyed")}}class m{constructor(e={}){this.checkCount=0,this.timerId=null,this.isBlankScreen=!1,this.config={detectionDelay:e.detectionDelay||3e3,minElements:e.minElements||10,checkInterval:e.checkInterval||1e3,maxChecks:e.maxChecks||5,checkPerformance:e.checkPerformance!==!1,customCheck:e.customCheck||(()=>!1)}}start(e){console.log("[BlankScreenDetector] Starting blank screen detection..."),console.log("[BlankScreenDetector] Config:",this.config),setTimeout(()=>{console.log("[BlankScreenDetector] Detection delay passed, starting first check..."),this.performCheck(e)},this.config.detectionDelay)}performCheck(e){this.checkCount++,console.log(`[BlankScreenDetector] Check #${this.checkCount}/${this.config.maxChecks}`);const t=this.checkIfBlank();if(console.log("[BlankScreenDetector] Is blank screen?",t),t&&!this.isBlankScreen){console.log("[BlankScreenDetector] Blank screen detected for the first time!"),this.isBlankScreen=!0;const n=this.generateReport();console.log("[BlankScreenDetector] Generated report:",n),e(n)}this.checkCount<this.config.maxChecks&&!t?(this.timerId=window.setTimeout(()=>{this.performCheck(e)},this.config.checkInterval),console.log(`[BlankScreenDetector] Scheduling next check in ${this.config.checkInterval}ms`)):console.log("[BlankScreenDetector] Stopping checks. Count:",this.checkCount,"Is blank:",t)}checkIfBlank(){if(this.config.customCheck())return console.log("[BlankScreenDetector] Custom check returned true"),!0;const e=this.checkDOMElements();if(console.log("[BlankScreenDetector] DOM check result:",e),e.isBlank)return console.log("[BlankScreenDetector] DOM check indicates blank screen"),!0;if(this.config.checkPerformance){const t=this.checkPerformanceTiming();if(console.log("[BlankScreenDetector] Performance check result:",t),t.isBlank)return console.log("[BlankScreenDetector] Performance check indicates blank screen"),!0}return console.log("[BlankScreenDetector] All checks passed, not a blank screen"),!1}checkDOMElements(){var a;const e=document.querySelectorAll("*").length,t=((a=document.body)==null?void 0:a.children.length)||0,n=!!document.body,i=t>0,o=document.querySelectorAll("#blank-page, #minimal-page, #temp-status").length,r=document.querySelectorAll("script").length,s=e-o-r,c=!n||s<this.config.minElements||!i,l={totalElements:e,bodyElements:t,hasBody:n,hasContent:i,testElements:o,scriptElements:r,elementsWithoutTestAndScripts:s,minElements:this.config.minElements};return console.log("[BlankScreenDetector] 详细DOM信息:",l),{isBlank:c,info:l}}checkPerformanceTiming(){var l;if(!window.performance||!window.performance.timing)return{isBlank:!1};const e=window.performance.timing,t=e.navigationStart,n=e.domContentLoadedEventEnd-t,i=e.loadEventEnd-t;let o,r;const s=(l=performance.getEntriesByType)==null?void 0:l.call(performance,"paint");if(s){const a=s.find(f=>f.name==="first-paint"),u=s.find(f=>f.name==="first-contentful-paint");o=a==null?void 0:a.startTime,r=u==null?void 0:u.startTime}return{isBlank:i>0&&(o===void 0||r===void 0)&&n>5e3,timing:{domContentLoaded:n,loadComplete:i,firstPaint:o,firstContentfulPaint:r}}}generateReport(){var n;const e=this.checkDOMElements(),t=this.config.checkPerformance?this.checkPerformanceTiming():{};return{type:"blank-screen",message:"检测到白屏:页面加载后无内容渲染",context:{timestamp:Date.now(),url:window.location.href,domElements:document.querySelectorAll("*").length,bodyElements:((n=document.body)==null?void 0:n.children.length)||0,hasContent:e.info.hasContent,performanceTiming:t.timing}}}stop(){console.log("[BlankScreenDetector] Stopping blank screen detection..."),this.timerId!==null&&(window.clearTimeout(this.timerId),this.timerId=null,console.log("[BlankScreenDetector] Cleared timeout timer")),console.log("[BlankScreenDetector] Blank screen detection stopped")}reset(){this.stop(),this.checkCount=0,this.isBlankScreen=!1}}function k(h){return new m(h)}class d extends p{constructor(e){super(e),this.originalFetch=null,this.originalXHR=null,this.blankScreenDetector=null,this.config=e}init(){var o,r,s,c;if(super.init(),typeof window>"u"){console.warn("[ErrorMonitorWeb] Not in browser environment");return}const e=((o=this.config.autoCapture)==null?void 0:o.js)!==!1&&this.config.captureJsErrors!==!1,t=((r=this.config.autoCapture)==null?void 0:r.promise)!==!1&&this.config.capturePromiseErrors!==!1,n=((s=this.config.autoCapture)==null?void 0:s.network)!==!1&&this.config.captureNetworkErrors!==!1,i=((c=this.config.autoCapture)==null?void 0:c.resource)!==!1&&this.config.captureResourceErrors!==!1;e&&this.setupJsErrorHandler(),t&&this.setupPromiseErrorHandler(),n&&this.setupNetworkErrorHandler(),i&&this.setupResourceErrorHandler(),this.config.blankScreenDetection&&this.setupBlankScreenDetection(),console.log("[ErrorMonitorWeb] Web handlers initialized")}setupJsErrorHandler(){window.addEventListener("error",e=>{var t;this.capture({type:"js",message:e.message,stack:(t=e.error)==null?void 0:t.stack,context:{filename:e.filename,lineno:e.lineno,colno:e.colno}})})}setupPromiseErrorHandler(){window.addEventListener("unhandledrejection",e=>{var t,n;this.capture({type:"promise",message:((t=e.reason)==null?void 0:t.message)||String(e.reason),stack:(n=e.reason)==null?void 0:n.stack,context:{reason:e.reason}})})}setupNetworkErrorHandler(){if(typeof window.fetch<"u"){this.originalFetch=window.fetch;const e=this;window.fetch=function(...t){return e.originalFetch.apply(this,t).catch(n=>{var r;const i=typeof t[0]=="string"?t[0]:String(t[0]),o=((r=t[1])==null?void 0:r.method)||"GET";throw e.capture({type:"network",message:`Network error: ${o} ${i}`,context:{url:i,method:o,error:n.message}}),n})}}if(typeof window.XMLHttpRequest<"u"){this.originalXHR=window.XMLHttpRequest;const e=this,t=this.originalXHR;window.XMLHttpRequest=function(){const n=new t,i=n.open,o=n.send;let r="",s="";return n.open=function(...c){return s=c[0]||"GET",r=String(c[1]||""),i.apply(this,c)},n.send=function(...c){return n.addEventListener("error",()=>{e.capture({type:"network",message:`XHR error: ${s} ${r}`,context:{url:r,method:s,status:n.status}})}),o.apply(this,c)},n}}}setupResourceErrorHandler(){window.addEventListener("error",e=>{if(e.target!==window){const t=e.target;this.capture({type:"resource",message:`Resource load error: ${t.tagName}`,context:{tagName:t.tagName,src:t.src||t.href}})}},!0)}setupBlankScreenDetection(){console.log("[ErrorMonitorWeb] Setting up blank screen detection...");const e=typeof this.config.blankScreenDetection=="boolean"?{}:this.config.blankScreenDetection;console.log("[ErrorMonitorWeb] Blank screen config:",e),this.blankScreenDetector=k(e),this.blankScreenDetector.start(t=>{console.log("[ErrorMonitorWeb] Blank screen detected!",t),this.capture({type:t.type,message:t.message,context:t.context})}),console.log("[ErrorMonitorWeb] Blank screen detection started")}captureError(e,t){this.capture({type:"custom",message:e.message,stack:e.stack,context:t})}captureMessage(e,t="info"){this.capture({type:"custom",message:e,context:{level:t}})}destroy(){console.log("[ErrorMonitorWeb] Destroying instance..."),this.blankScreenDetector&&(console.log("[ErrorMonitorWeb] Stopping blank screen detector..."),this.blankScreenDetector.stop(),this.blankScreenDetector=null),this.originalFetch&&window.fetch!==this.originalFetch&&(window.fetch=this.originalFetch),this.originalXHR&&window.XMLHttpRequest!==this.originalXHR&&(window.XMLHttpRequest=this.originalXHR),super.destroy(),console.log("[ErrorMonitorWeb] Instance destroyed")}}function w(h){return new d(h)}exports.BlankScreenDetector=m;exports.ErrorMonitor=p;exports.ErrorMonitorWeb=d;exports.createBlankScreenDetector=k;exports.createErrorMonitorWeb=w;exports.default=d;
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","sources":["../../core/dist/index.mjs","../src/blank-screen-detector.ts","../src/index.ts"],"sourcesContent":["function h() {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n}\nfunction l() {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 15)}`;\n}\nclass g {\n constructor(e) {\n this.isInitialized = !1, this.breadcrumbs = [], this.maxBreadcrumbs = 50, this.plugins = [], this.sessionId = h(), this.config = {\n autoCapture: {\n js: !0,\n promise: !0,\n network: !0,\n resource: !0,\n console: !1\n },\n filter: {\n ignoreErrors: [],\n ignoreUrls: [],\n minLevel: \"info\"\n },\n report: {\n delay: 1e3,\n batchSize: 10\n },\n sampleRate: 1,\n errorSampleRate: 1,\n enabled: !0,\n debug: !1,\n ...e\n };\n }\n /**\n * 更新配置\n */\n updateConfig(e) {\n this.config = { ...this.config, ...e }, this.config.debug && console.log(\"[ErrorMonitor] Config updated:\", this.config);\n }\n /**\n * 启用SDK\n */\n enable() {\n this.config.enabled = !0, console.log(\"[ErrorMonitor] SDK enabled\");\n }\n /**\n * 禁用SDK\n */\n disable() {\n this.config.enabled = !1, console.log(\"[ErrorMonitor] SDK disabled\");\n }\n /**\n * 添加错误过滤器\n */\n addFilter(e) {\n this.config.filter || (this.config.filter = {}), this.config.filter.ignoreErrors || (this.config.filter.ignoreErrors = []), this.config.filter.ignoreErrors.push(e);\n }\n /**\n * 移除错误过滤器\n */\n removeFilter(e) {\n var r;\n if (!((r = this.config.filter) != null && r.ignoreErrors)) return;\n const t = this.config.filter.ignoreErrors.indexOf(e);\n t > -1 && this.config.filter.ignoreErrors.splice(t, 1);\n }\n /**\n * 设置采样率\n */\n setSampleRate(e) {\n this.config.sampleRate = Math.max(0, Math.min(1, e));\n }\n /**\n * 设置错误采样率\n */\n setErrorSampleRate(e) {\n this.config.errorSampleRate = Math.max(0, Math.min(1, e));\n }\n /**\n * 初始化监控\n */\n init() {\n if (this.isInitialized) {\n console.warn(\"[ErrorMonitor] Already initialized\");\n return;\n }\n this.isInitialized = !0, this.plugins.forEach((e) => {\n var t;\n (t = e.setup) == null || t.call(e, this);\n }), console.log(\"[ErrorMonitor] Initialized with appId:\", this.config.appId);\n }\n /**\n * 注册插件\n */\n use(e) {\n var t;\n this.plugins.push(e), this.isInitialized && ((t = e.setup) == null || t.call(e, this));\n }\n /**\n * 捕获错误(支持选项)\n */\n capture(e, t) {\n var c, d;\n if (!this.isInitialized) {\n console.warn(\"[ErrorMonitor] Not initialized\");\n return;\n }\n if (this.config.enabled === !1)\n return;\n const r = e instanceof Error ? {\n type: \"custom\",\n message: e.message,\n stack: e.stack,\n context: {}\n } : e, i = {\n level: \"error\",\n tags: {},\n extra: {},\n user: {},\n skipSampling: !1,\n skipFilter: !1,\n ...t\n };\n if (!i.skipFilter && this.shouldFilter(r)) {\n this.config.debug && console.log(\"[ErrorMonitor] Error filtered:\", r.message);\n return;\n }\n if (!i.skipSampling && this.config.errorSampleRate !== void 0 && Math.random() > this.config.errorSampleRate)\n return;\n let s = r;\n for (const n of this.plugins) {\n const a = (c = n.beforeCapture) == null ? void 0 : c.call(n, r);\n if (a === null)\n return;\n a !== void 0 && (s = a);\n }\n const o = {\n appId: this.config.appId,\n timestamp: Date.now(),\n sessionId: this.sessionId,\n eventId: l(),\n type: s.type,\n level: i.level,\n message: s.message,\n stack: s.stack,\n context: {\n userAgent: typeof navigator < \"u\" ? navigator.userAgent : \"\",\n url: typeof location < \"u\" ? location.href : \"\",\n viewport: {\n width: typeof window < \"u\" ? window.innerWidth : 0,\n height: typeof window < \"u\" ? window.innerHeight : 0\n },\n userId: i.user.id || this.config.userId,\n tags: { ...this.config.tags, ...i.tags }\n },\n breadcrumbs: [...this.breadcrumbs],\n extra: { ...s.context, ...i.extra }\n };\n for (const n of this.plugins) {\n const a = (d = n.afterCapture) == null ? void 0 : d.call(n, o);\n a !== void 0 && Object.assign(o, a);\n }\n this.report(o);\n }\n /**\n * 检查是否应该过滤此错误\n */\n shouldFilter(e) {\n var s;\n if (!this.config.filter) return !1;\n const { ignoreErrors: t, ignoreUrls: r, minLevel: i } = this.config.filter;\n if (t && t.length > 0) {\n for (const o of t)\n if (o.test(e.message))\n return !0;\n }\n if (r && r.length > 0 && ((s = e.context) != null && s.url)) {\n for (const o of r)\n if (o.test(e.context.url))\n return !0;\n }\n return !1;\n }\n /**\n * 手动上报错误(简化的API)\n */\n captureError(e, t) {\n this.capture(e, t);\n }\n /**\n * 手动上报消息\n */\n captureMessage(e, t = \"info\", r) {\n this.capture({\n type: \"custom\",\n message: e,\n context: {}\n }, { ...r, level: t });\n }\n /**\n * 上报错误\n */\n report(e) {\n var r;\n let t = e;\n for (const i of this.plugins) {\n const s = (r = i.beforeReport) == null ? void 0 : r.call(i, e);\n s !== void 0 && (t = s);\n }\n this.sendToServer(t);\n }\n /**\n * 添加面包屑\n */\n addBreadcrumb(e) {\n this.breadcrumbs.push({\n timestamp: e.timestamp || Date.now(),\n type: e.type,\n message: e.message,\n data: e.data\n }), this.breadcrumbs.length > this.maxBreadcrumbs && this.breadcrumbs.shift();\n }\n /**\n * 生成ID\n */\n generateId() {\n return l();\n }\n /**\n * 设置用户信息\n */\n setUser(e) {\n this.config.userId = e.id, this.config.tags = { ...this.config.tags, ...e };\n }\n /**\n * 发送到服务端\n */\n sendToServer(e) {\n if (typeof navigator > \"u\") return;\n const t = JSON.stringify(e);\n if (navigator.sendBeacon) {\n const r = new Blob([t], { type: \"application/json\" });\n navigator.sendBeacon(this.config.dsn, r);\n return;\n }\n typeof fetch < \"u\" && fetch(this.config.dsn, {\n method: \"POST\",\n body: t,\n keepalive: !0,\n headers: {\n \"Content-Type\": \"application/json\"\n }\n }).catch((r) => {\n console.error(\"[ErrorMonitor] Failed to send report:\", r);\n });\n }\n /**\n * 销毁实例\n */\n destroy() {\n this.plugins.forEach((e) => {\n var t;\n (t = e.teardown) == null || t.call(e);\n }), this.plugins = [], this.breadcrumbs = [], this.isInitialized = !1, console.log(\"[ErrorMonitor] Destroyed\");\n }\n}\nfunction u(f) {\n return new g(f);\n}\nexport {\n g as ErrorMonitor,\n u as createErrorMonitor\n};\n//# sourceMappingURL=index.mjs.map\n","/**\n * 白屏检测模块\n * 检测页面是否白屏(无内容渲染)\n */\n\nexport interface BlankScreenConfig {\n // 检测阈值:页面加载后多久开始检测(毫秒)\n detectionDelay?: number\n // 最小DOM元素数量阈值\n minElements?: number\n // 检测间隔(毫秒)\n checkInterval?: number\n // 最大检测次数\n maxChecks?: number\n // 是否检测Performance API\n checkPerformance?: boolean\n // 自定义检测函数\n customCheck?: () => boolean\n}\n\nexport interface BlankScreenReport {\n type: 'blank-screen'\n message: string\n context: {\n timestamp: number\n url: string\n domElements: number\n bodyElements: number\n hasContent: boolean\n performanceTiming?: {\n domContentLoaded?: number\n loadComplete?: number\n firstPaint?: number\n firstContentfulPaint?: number\n }\n }\n}\n\n/**\n * 白屏检测器类\n */\nexport class BlankScreenDetector {\n private config: Required<BlankScreenConfig>\n private checkCount: number = 0\n private timerId: number | null = null\n private isBlankScreen: boolean = false\n\n constructor(config: BlankScreenConfig = {}) {\n this.config = {\n detectionDelay: config.detectionDelay || 3000, // 3秒后开始检测\n minElements: config.minElements || 10, // 最少10个元素\n checkInterval: config.checkInterval || 1000, // 每秒检测一次\n maxChecks: config.maxChecks || 5, // 最多检测5次\n checkPerformance: config.checkPerformance !== false,\n customCheck: config.customCheck || (() => false)\n }\n }\n\n /**\n * 开始检测\n */\n start(callback: (report: BlankScreenReport) => void): void {\n console.log('[BlankScreenDetector] Starting blank screen detection...')\n console.log('[BlankScreenDetector] Config:', this.config)\n\n // 延迟开始检测,等待页面加载\n setTimeout(() => {\n console.log('[BlankScreenDetector] Detection delay passed, starting first check...')\n this.performCheck(callback)\n }, this.config.detectionDelay)\n }\n\n /**\n * 执行检测\n */\n private performCheck(callback: (report: BlankScreenReport) => void): void {\n this.checkCount++\n console.log(`[BlankScreenDetector] Check #${this.checkCount}/${this.config.maxChecks}`)\n\n const isBlank = this.checkIfBlank()\n console.log('[BlankScreenDetector] Is blank screen?', isBlank)\n\n if (isBlank && !this.isBlankScreen) {\n // 首次检测到白屏\n console.log('[BlankScreenDetector] Blank screen detected for the first time!')\n this.isBlankScreen = true\n const report = this.generateReport()\n console.log('[BlankScreenDetector] Generated report:', report)\n callback(report)\n }\n\n // 如果还未达到最大检测次数,继续检测\n if (this.checkCount < this.config.maxChecks && !isBlank) {\n this.timerId = window.setTimeout(() => {\n this.performCheck(callback)\n }, this.config.checkInterval)\n console.log(`[BlankScreenDetector] Scheduling next check in ${this.config.checkInterval}ms`)\n } else {\n console.log('[BlankScreenDetector] Stopping checks. Count:', this.checkCount, 'Is blank:', isBlank)\n }\n }\n\n /**\n * 检查是否白屏\n */\n private checkIfBlank(): boolean {\n // 1. 检查自定义检测函数\n if (this.config.customCheck()) {\n console.log('[BlankScreenDetector] Custom check returned true')\n return true\n }\n\n // 2. 检查DOM元素数量\n const domCheck = this.checkDOMElements()\n console.log('[BlankScreenDetector] DOM check result:', domCheck)\n if (domCheck.isBlank) {\n console.log('[BlankScreenDetector] DOM check indicates blank screen')\n return true\n }\n\n // 3. 检查Performance API\n if (this.config.checkPerformance) {\n const perfCheck = this.checkPerformanceTiming()\n console.log('[BlankScreenDetector] Performance check result:', perfCheck)\n if (perfCheck.isBlank) {\n console.log('[BlankScreenDetector] Performance check indicates blank screen')\n return true\n }\n }\n\n console.log('[BlankScreenDetector] All checks passed, not a blank screen')\n return false\n }\n\n /**\n * 检查DOM元素\n */\n private checkDOMElements(): { isBlank: boolean; info: any } {\n const totalElements = document.querySelectorAll('*').length\n const bodyElements = document.body?.children.length || 0\n\n // 检查body是否存在且不为空\n const hasBody = !!document.body\n const hasContent = bodyElements > 0\n\n // 排除测试相关的元素(blank-page, minimal-page, temp-status等)\n const testElements = document.querySelectorAll('#blank-page, #minimal-page, #temp-status').length\n\n // 排除script标签(测试时script标签不算作内容)\n const scriptElements = document.querySelectorAll('script').length\n\n const elementsWithoutTestAndScripts = totalElements - testElements - scriptElements\n\n // 改进的白屏判断:排除测试元素和script后仍然很少,才认为是白屏\n const isBlank = !hasBody || elementsWithoutTestAndScripts < this.config.minElements || !hasContent\n\n const info = {\n totalElements,\n bodyElements,\n hasBody,\n hasContent,\n testElements,\n scriptElements,\n elementsWithoutTestAndScripts,\n minElements: this.config.minElements\n }\n\n console.log('[BlankScreenDetector] 详细DOM信息:', info)\n\n return {\n isBlank,\n info\n }\n }\n\n /**\n * 检查Performance API\n */\n private checkPerformanceTiming(): { isBlank: boolean; timing?: any } {\n if (!window.performance || !window.performance.timing) {\n return { isBlank: false }\n }\n\n const timing = window.performance.timing\n const navigationStart = timing.navigationStart\n\n const domContentLoaded = timing.domContentLoadedEventEnd - navigationStart\n const loadComplete = timing.loadEventEnd - navigationStart\n\n // 获取首次绘制时间\n let firstPaint: number | undefined\n let firstContentfulPaint: number | undefined\n\n const perfEntries = performance.getEntriesByType?.('paint') as PerformanceEntry[]\n if (perfEntries) {\n const fp = perfEntries.find(e => e.name === 'first-paint')\n const fcp = perfEntries.find(e => e.name === 'first-contentful-paint')\n firstPaint = fp?.startTime\n firstContentfulPaint = fcp?.startTime\n }\n\n // 如果页面加载完成但没有任何绘制,可能是白屏\n const isBlank =\n loadComplete > 0 &&\n (firstPaint === undefined || firstContentfulPaint === undefined) &&\n domContentLoaded > 5000 // DOM加载超过5秒但没有绘制\n\n return {\n isBlank,\n timing: {\n domContentLoaded,\n loadComplete,\n firstPaint,\n firstContentfulPaint\n }\n }\n }\n\n /**\n * 生成报告\n */\n private generateReport(): BlankScreenReport {\n const domInfo = this.checkDOMElements()\n const perfInfo = this.config.checkPerformance ? this.checkPerformanceTiming() : {}\n\n return {\n type: 'blank-screen',\n message: '检测到白屏:页面加载后无内容渲染',\n context: {\n timestamp: Date.now(),\n url: window.location.href,\n domElements: document.querySelectorAll('*').length,\n bodyElements: document.body?.children.length || 0,\n hasContent: domInfo.info.hasContent,\n performanceTiming: perfInfo.timing\n }\n }\n }\n\n /**\n * 停止检测\n */\n stop(): void {\n console.log('[BlankScreenDetector] Stopping blank screen detection...')\n if (this.timerId !== null) {\n window.clearTimeout(this.timerId)\n this.timerId = null\n console.log('[BlankScreenDetector] Cleared timeout timer')\n }\n console.log('[BlankScreenDetector] Blank screen detection stopped')\n }\n\n /**\n * 重置检测器\n */\n reset(): void {\n this.stop()\n this.checkCount = 0\n this.isBlankScreen = false\n }\n}\n\n/**\n * 创建白屏检测器实例\n */\nexport function createBlankScreenDetector(config?: BlankScreenConfig): BlankScreenDetector {\n return new BlankScreenDetector(config)\n}\n","/**\n * Error Monitor Web\n * Web端错误监控模块\n */\n\nimport { ErrorMonitor, Config } from 'error-monitor-core'\nimport {\n BlankScreenDetector,\n BlankScreenConfig,\n createBlankScreenDetector\n} from './blank-screen-detector'\n\n// 导出核心\nexport { ErrorMonitor } from 'error-monitor-core'\nexport type { Config, Plugin, Breadcrumb } from 'error-monitor-core'\n\n// 导出白屏检测\nexport { BlankScreenDetector, createBlankScreenDetector }\nexport type { BlankScreenConfig, BlankScreenReport } from './blank-screen-detector'\n\n/**\n * Web端配置\n */\nexport interface WebConfig extends Config {\n // 是否自动捕获全局错误 (已弃用,请使用 autoCapture)\n captureJsErrors?: boolean\n // 是否捕获Promise错误 (已弃用,请使用 autoCapture)\n capturePromiseErrors?: boolean\n // 是否捕获网络错误 (已弃用,请使用 autoCapture)\n captureNetworkErrors?: boolean\n // 是否捕获资源加载错误 (已弃用,请使用 autoCapture)\n captureResourceErrors?: boolean\n // 是否启用白屏检测\n blankScreenDetection?: boolean | BlankScreenConfig\n // 自定义上报函数\n customReporter?: (data: any) => void\n}\n\n/**\n * Web端错误监控类\n */\nexport class ErrorMonitorWeb extends ErrorMonitor {\n protected config: WebConfig\n private originalFetch: typeof fetch | null = null\n private originalXHR: typeof XMLHttpRequest | null = null\n private blankScreenDetector: BlankScreenDetector | null = null\n\n constructor(config: WebConfig) {\n super(config)\n this.config = config\n }\n\n /**\n * 初始化Web端监控\n */\n init(): void {\n super.init()\n\n if (typeof window === 'undefined') {\n console.warn('[ErrorMonitorWeb] Not in browser environment')\n return\n }\n\n // 支持新旧两种配置格式\n // 新格式: autoCapture.js\n // 旧格式: captureJsErrors\n const captureJs = this.config.autoCapture?.js !== false && this.config.captureJsErrors !== false\n const capturePromise = this.config.autoCapture?.promise !== false && this.config.capturePromiseErrors !== false\n const captureNetwork = this.config.autoCapture?.network !== false && this.config.captureNetworkErrors !== false\n const captureResource = this.config.autoCapture?.resource !== false && this.config.captureResourceErrors !== false\n\n // 自动捕获各种错误\n if (captureJs) {\n this.setupJsErrorHandler()\n }\n\n if (capturePromise) {\n this.setupPromiseErrorHandler()\n }\n\n if (captureNetwork) {\n this.setupNetworkErrorHandler()\n }\n\n if (captureResource) {\n this.setupResourceErrorHandler()\n }\n\n // 初始化白屏检测\n if (this.config.blankScreenDetection) {\n this.setupBlankScreenDetection()\n }\n\n console.log('[ErrorMonitorWeb] Web handlers initialized')\n }\n\n /**\n * JavaScript错误处理\n */\n private setupJsErrorHandler(): void {\n window.addEventListener('error', (event) => {\n this.capture({\n type: 'js',\n message: event.message,\n stack: event.error?.stack,\n context: {\n filename: event.filename,\n lineno: event.lineno,\n colno: event.colno\n }\n })\n })\n }\n\n /**\n * Promise错误处理\n */\n private setupPromiseErrorHandler(): void {\n window.addEventListener('unhandledrejection', (event) => {\n this.capture({\n type: 'promise',\n message: event.reason?.message || String(event.reason),\n stack: event.reason?.stack,\n context: {\n reason: event.reason\n }\n })\n })\n }\n\n /**\n * 网络请求错误处理\n */\n private setupNetworkErrorHandler(): void {\n // 拦截fetch\n if (typeof window.fetch !== 'undefined') {\n this.originalFetch = window.fetch\n const self = this\n\n window.fetch = function (...args: Parameters<typeof fetch>) {\n return self.originalFetch!\n .apply(this, args as any)\n .catch((error) => {\n const url = typeof args[0] === 'string' ? args[0] : String(args[0])\n const method = args[1]?.method || 'GET'\n\n self.capture({\n type: 'network',\n message: `Network error: ${method} ${url}`,\n context: {\n url,\n method,\n error: error.message\n }\n })\n\n throw error\n })\n }\n }\n\n // 拦截XMLHttpRequest(简化版)\n if (typeof window.XMLHttpRequest !== 'undefined') {\n this.originalXHR = window.XMLHttpRequest\n const self = this\n\n const OriginalXHR = this.originalXHR\n window.XMLHttpRequest = function () {\n const xhr = new OriginalXHR()\n const originalOpen = xhr.open\n const originalSend = xhr.send\n let url = ''\n let method = ''\n\n xhr.open = function (...args: any[]) {\n method = args[0] || 'GET'\n url = String(args[1] || '')\n return originalOpen.apply(this, args as any)\n }\n\n xhr.send = function (...args: any[]) {\n xhr.addEventListener('error', () => {\n self.capture({\n type: 'network',\n message: `XHR error: ${method} ${url}`,\n context: {\n url,\n method,\n status: xhr.status\n }\n })\n })\n\n return originalSend.apply(this, args as any)\n }\n\n return xhr\n } as any\n }\n }\n\n /**\n * 资源加载错误处理\n */\n private setupResourceErrorHandler(): void {\n window.addEventListener('error', (event) => {\n if (event.target !== window) {\n const target = event.target as HTMLElement\n this.capture({\n type: 'resource',\n message: `Resource load error: ${target.tagName}`,\n context: {\n tagName: target.tagName,\n src: (target as any).src || (target as any).href\n }\n })\n }\n }, true)\n }\n\n /**\n * 白屏检测\n */\n private setupBlankScreenDetection(): void {\n console.log('[ErrorMonitorWeb] Setting up blank screen detection...')\n const config =\n typeof this.config.blankScreenDetection === 'boolean'\n ? {}\n : this.config.blankScreenDetection\n\n console.log('[ErrorMonitorWeb] Blank screen config:', config)\n this.blankScreenDetector = createBlankScreenDetector(config)\n\n this.blankScreenDetector.start((report) => {\n console.log('[ErrorMonitorWeb] Blank screen detected!', report)\n this.capture({\n type: report.type,\n message: report.message,\n context: report.context\n })\n })\n\n console.log('[ErrorMonitorWeb] Blank screen detection started')\n }\n\n /**\n * 手动上报错误\n */\n captureError(error: Error, context?: Record<string, any>): void {\n this.capture({\n type: 'custom',\n message: error.message,\n stack: error.stack,\n context\n })\n }\n\n /**\n * 手动上报消息\n */\n captureMessage(message: string, level: string = 'info'): void {\n this.capture({\n type: 'custom',\n message,\n context: { level }\n })\n }\n\n /**\n * 销毁实例\n */\n destroy(): void {\n console.log('[ErrorMonitorWeb] Destroying instance...')\n\n // 停止白屏检测\n if (this.blankScreenDetector) {\n console.log('[ErrorMonitorWeb] Stopping blank screen detector...')\n this.blankScreenDetector.stop()\n this.blankScreenDetector = null\n }\n\n // 恢复原生方法\n if (this.originalFetch && window.fetch !== this.originalFetch) {\n window.fetch = this.originalFetch\n }\n\n if (this.originalXHR && window.XMLHttpRequest !== this.originalXHR) {\n window.XMLHttpRequest = this.originalXHR\n }\n\n super.destroy()\n\n console.log('[ErrorMonitorWeb] Instance destroyed')\n }\n}\n\n/**\n * 创建Web端实例工厂函数\n */\nexport function createErrorMonitorWeb(config: WebConfig): ErrorMonitorWeb {\n return new ErrorMonitorWeb(config)\n}\n\n// 默认导出\nexport default ErrorMonitorWeb\n"],"names":["h","l","g","r","t","c","d","i","n","o","s","BlankScreenDetector","config","callback","isBlank","report","domCheck","perfCheck","totalElements","bodyElements","_a","hasBody","hasContent","testElements","scriptElements","elementsWithoutTestAndScripts","info","timing","navigationStart","domContentLoaded","loadComplete","firstPaint","firstContentfulPaint","perfEntries","fp","e","fcp","domInfo","perfInfo","createBlankScreenDetector","ErrorMonitorWeb","ErrorMonitor","captureJs","capturePromise","_b","captureNetwork","_c","captureResource","_d","event","self","args","error","url","method","OriginalXHR","xhr","originalOpen","originalSend","target","context","message","level","createErrorMonitorWeb"],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { Breadcrumb } from 'error-monitor-core';
2
+ import { Config } from 'error-monitor-core';
3
+ import { ErrorMonitor } from 'error-monitor-core';
4
+ import { Plugin as Plugin_2 } from 'error-monitor-core';
5
+
6
+ export declare interface BlankScreenConfig {
7
+ detectionDelay?: number;
8
+ minElements?: number;
9
+ checkInterval?: number;
10
+ maxChecks?: number;
11
+ checkPerformance?: boolean;
12
+ customCheck?: () => boolean;
13
+ }
14
+
15
+ export declare class BlankScreenDetector {
16
+ private config;
17
+ private checkCount;
18
+ private timerId;
19
+ private isBlankScreen;
20
+ constructor(config?: BlankScreenConfig);
21
+ start(callback: (report: BlankScreenReport) => void): void;
22
+ private performCheck;
23
+ private checkIfBlank;
24
+ private checkDOMElements;
25
+ private checkPerformanceTiming;
26
+ private generateReport;
27
+ stop(): void;
28
+ reset(): void;
29
+ }
30
+
31
+ export declare interface BlankScreenReport {
32
+ type: 'blank-screen';
33
+ message: string;
34
+ context: {
35
+ timestamp: number;
36
+ url: string;
37
+ domElements: number;
38
+ bodyElements: number;
39
+ hasContent: boolean;
40
+ performanceTiming?: {
41
+ domContentLoaded?: number;
42
+ loadComplete?: number;
43
+ firstPaint?: number;
44
+ firstContentfulPaint?: number;
45
+ };
46
+ };
47
+ }
48
+
49
+ export { Breadcrumb }
50
+
51
+ export { Config }
52
+
53
+ export declare function createBlankScreenDetector(config?: BlankScreenConfig): BlankScreenDetector;
54
+
55
+ export declare function createErrorMonitorWeb(config: WebConfig): ErrorMonitorWeb;
56
+
57
+ export { ErrorMonitor }
58
+
59
+ declare class ErrorMonitorWeb extends ErrorMonitor {
60
+ protected config: WebConfig;
61
+ private originalFetch;
62
+ private originalXHR;
63
+ private blankScreenDetector;
64
+ constructor(config: WebConfig);
65
+ init(): void;
66
+ private setupJsErrorHandler;
67
+ private setupPromiseErrorHandler;
68
+ private setupNetworkErrorHandler;
69
+ private setupResourceErrorHandler;
70
+ private setupBlankScreenDetection;
71
+ captureError(error: Error, context?: Record<string, any>): void;
72
+ captureMessage(message: string, level?: string): void;
73
+ destroy(): void;
74
+ }
75
+ export { ErrorMonitorWeb }
76
+ export default ErrorMonitorWeb;
77
+
78
+ export { Plugin_2 as Plugin }
79
+
80
+ export declare interface WebConfig extends Config {
81
+ captureJsErrors?: boolean;
82
+ capturePromiseErrors?: boolean;
83
+ captureNetworkErrors?: boolean;
84
+ captureResourceErrors?: boolean;
85
+ blankScreenDetection?: boolean | BlankScreenConfig;
86
+ customReporter?: (data: any) => void;
87
+ }
88
+
89
+ export { }