@syntropysoft/syntropyfront 0.2.3 → 0.2.4
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/README.md +85 -0
- package/dist/index.cjs +328 -328
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +328 -328
- package/dist/index.js.map +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +19 -10
package/dist/index.js
CHANGED
|
@@ -3,33 +3,33 @@
|
|
|
3
3
|
* Responsabilidad única: Almacenar y gestionar breadcrumbs
|
|
4
4
|
*/
|
|
5
5
|
class BreadcrumbManager {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
constructor() {
|
|
7
|
+
this.breadcrumbs = [];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
add(category, message, data = {}) {
|
|
11
|
+
const breadcrumb = {
|
|
12
|
+
category,
|
|
13
|
+
message,
|
|
14
|
+
data,
|
|
15
|
+
timestamp: new Date().toISOString()
|
|
16
|
+
};
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
this.breadcrumbs.push(breadcrumb);
|
|
19
|
+
return breadcrumb;
|
|
20
|
+
}
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
getAll() {
|
|
23
|
+
return this.breadcrumbs;
|
|
24
|
+
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
clear() {
|
|
27
|
+
this.breadcrumbs = [];
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
getCount() {
|
|
31
|
+
return this.breadcrumbs.length;
|
|
32
|
+
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
/**
|
|
@@ -37,33 +37,33 @@ class BreadcrumbManager {
|
|
|
37
37
|
* Responsabilidad única: Formatear y gestionar errores
|
|
38
38
|
*/
|
|
39
39
|
class ErrorManager {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
constructor() {
|
|
41
|
+
this.errors = [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
send(error, context = {}) {
|
|
45
|
+
const errorData = {
|
|
46
|
+
message: error.message,
|
|
47
|
+
stack: error.stack,
|
|
48
|
+
context,
|
|
49
|
+
timestamp: new Date().toISOString()
|
|
50
|
+
};
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
this.errors.push(errorData);
|
|
53
|
+
return errorData;
|
|
54
|
+
}
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
56
|
+
getAll() {
|
|
57
|
+
return this.errors;
|
|
58
|
+
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
clear() {
|
|
61
|
+
this.errors = [];
|
|
62
|
+
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
getCount() {
|
|
65
|
+
return this.errors.length;
|
|
66
|
+
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
/**
|
|
@@ -71,48 +71,48 @@ class ErrorManager {
|
|
|
71
71
|
* Responsabilidad única: Mostrar mensajes solo cuando hay errores
|
|
72
72
|
*/
|
|
73
73
|
class Logger {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
constructor() {
|
|
75
|
+
this.isSilent = true; // Por defecto silente
|
|
76
|
+
}
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
log(message, data = null) {
|
|
79
|
+
// No loggear nada en modo silente
|
|
80
|
+
if (this.isSilent) return;
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
82
|
+
if (data) {
|
|
83
|
+
console.log(message, data);
|
|
84
|
+
} else {
|
|
85
|
+
console.log(message);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
error(message, data = null) {
|
|
90
|
+
// SIEMPRE loggear errores (ignora modo silencioso)
|
|
91
|
+
if (data) {
|
|
92
|
+
console.error(message, data);
|
|
93
|
+
} else {
|
|
94
|
+
console.error(message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
warn(message, data = null) {
|
|
99
|
+
// Solo warnings importantes
|
|
100
|
+
if (data) {
|
|
101
|
+
console.warn(message, data);
|
|
102
|
+
} else {
|
|
103
|
+
console.warn(message);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Método para activar logging (solo para debug)
|
|
108
|
+
enableLogging() {
|
|
109
|
+
this.isSilent = false;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Método para desactivar logging
|
|
113
|
+
disableLogging() {
|
|
114
|
+
this.isSilent = true;
|
|
115
|
+
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
@@ -121,35 +121,35 @@ class Logger {
|
|
|
121
121
|
*/
|
|
122
122
|
|
|
123
123
|
class SyntropyFront {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
124
|
+
constructor() {
|
|
125
|
+
// Basic managers
|
|
126
|
+
this.breadcrumbManager = new BreadcrumbManager();
|
|
127
|
+
this.errorManager = new ErrorManager();
|
|
128
|
+
this.logger = new Logger();
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
130
|
+
// Default configuration
|
|
131
|
+
this.maxEvents = 50;
|
|
132
|
+
this.fetchConfig = null; // Complete fetch configuration
|
|
133
|
+
this.onErrorCallback = null; // User-defined error handler
|
|
134
|
+
this.isActive = false;
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
// Automatic capture
|
|
137
|
+
this.originalHandlers = {};
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
// Auto-initialize
|
|
140
|
+
this.init();
|
|
141
|
+
}
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
|
|
143
|
+
init() {
|
|
144
|
+
this.isActive = true;
|
|
145
145
|
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
// Configure automatic capture immediately
|
|
147
|
+
this.setupAutomaticCapture();
|
|
148
148
|
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
console.log('🚀 SyntropyFront: Initialized with automatic capture');
|
|
150
|
+
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
/**
|
|
153
153
|
* Configure SyntropyFront
|
|
154
154
|
* @param {Object} config - Configuration
|
|
155
155
|
* @param {number} config.maxEvents - Maximum number of events to store
|
|
@@ -158,266 +158,266 @@ class SyntropyFront {
|
|
|
158
158
|
* @param {Object} config.fetch.options - Fetch options (headers, method, etc.)
|
|
159
159
|
* @param {Function} config.onError - User-defined error handler callback
|
|
160
160
|
*/
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
161
|
+
configure(config = {}) {
|
|
162
|
+
this.maxEvents = config.maxEvents || this.maxEvents;
|
|
163
|
+
this.fetchConfig = config.fetch;
|
|
164
|
+
this.onErrorCallback = config.onError;
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
166
|
+
if (this.onErrorCallback) {
|
|
167
|
+
console.log(`✅ SyntropyFront: Configured - maxEvents: ${this.maxEvents}, custom error handler`);
|
|
168
|
+
} else if (this.fetchConfig) {
|
|
169
|
+
console.log(`✅ SyntropyFront: Configured - maxEvents: ${this.maxEvents}, endpoint: ${this.fetchConfig.url}`);
|
|
170
|
+
} else {
|
|
171
|
+
console.log(`✅ SyntropyFront: Configured - maxEvents: ${this.maxEvents}, console only`);
|
|
173
172
|
}
|
|
173
|
+
}
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
/**
|
|
176
176
|
* Configure automatic event capture
|
|
177
177
|
*/
|
|
178
|
-
|
|
179
|
-
|
|
178
|
+
setupAutomaticCapture() {
|
|
179
|
+
if (typeof window === 'undefined') return;
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
181
|
+
// Capture clicks
|
|
182
|
+
this.setupClickCapture();
|
|
183
183
|
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
// Capture errors
|
|
185
|
+
this.setupErrorCapture();
|
|
186
186
|
|
|
187
|
-
|
|
188
|
-
|
|
187
|
+
// Capture HTTP calls
|
|
188
|
+
this.setupHttpCapture();
|
|
189
189
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
190
|
+
// Capture console logs
|
|
191
|
+
this.setupConsoleCapture();
|
|
192
|
+
}
|
|
193
193
|
|
|
194
|
-
|
|
194
|
+
/**
|
|
195
195
|
* Capture user clicks
|
|
196
196
|
*/
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
197
|
+
setupClickCapture() {
|
|
198
|
+
const clickHandler = (event) => {
|
|
199
|
+
const element = event.target;
|
|
200
|
+
this.addBreadcrumb('user', 'click', {
|
|
201
|
+
element: element.tagName,
|
|
202
|
+
id: element.id,
|
|
203
|
+
className: element.className,
|
|
204
|
+
x: event.clientX,
|
|
205
|
+
y: event.clientY
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
document.addEventListener('click', clickHandler);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
213
|
* Automatically capture errors
|
|
214
214
|
*/
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
215
|
+
setupErrorCapture() {
|
|
216
|
+
// Save original handlers
|
|
217
|
+
this.originalHandlers.onerror = window.onerror;
|
|
218
|
+
this.originalHandlers.onunhandledrejection = window.onunhandledrejection;
|
|
219
|
+
|
|
220
|
+
// Intercept errors
|
|
221
|
+
window.onerror = (message, source, lineno, colno, error) => {
|
|
222
|
+
const errorPayload = {
|
|
223
|
+
type: 'uncaught_exception',
|
|
224
|
+
error: { message, source, lineno, colno, stack: error?.stack },
|
|
225
|
+
breadcrumbs: this.getBreadcrumbs(),
|
|
226
|
+
timestamp: new Date().toISOString()
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
this.handleError(errorPayload);
|
|
230
230
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
// Call original handler
|
|
232
|
+
if (this.originalHandlers.onerror) {
|
|
233
|
+
return this.originalHandlers.onerror(message, source, lineno, colno, error);
|
|
234
|
+
}
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
236
|
+
return false;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Intercept rejected promises
|
|
240
|
+
window.onunhandledrejection = (event) => {
|
|
241
|
+
const errorPayload = {
|
|
242
|
+
type: 'unhandled_rejection',
|
|
243
|
+
error: {
|
|
244
|
+
message: event.reason?.message || 'Promise rejection without message',
|
|
245
|
+
stack: event.reason?.stack,
|
|
246
|
+
},
|
|
247
|
+
breadcrumbs: this.getBreadcrumbs(),
|
|
248
|
+
timestamp: new Date().toISOString()
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
this.handleError(errorPayload);
|
|
252
252
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
253
|
+
// Call original handler
|
|
254
|
+
if (this.originalHandlers.onunhandledrejection) {
|
|
255
|
+
this.originalHandlers.onunhandledrejection(event);
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
261
|
* Capture HTTP calls
|
|
262
262
|
*/
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
263
|
+
setupHttpCapture() {
|
|
264
|
+
// Intercept fetch
|
|
265
|
+
const originalFetch = window.fetch;
|
|
266
|
+
window.fetch = (...args) => {
|
|
267
|
+
const [url, options] = args;
|
|
268
268
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
269
|
+
this.addBreadcrumb('http', 'fetch', {
|
|
270
|
+
url,
|
|
271
|
+
method: options?.method || 'GET'
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
return originalFetch(...args).then(response => {
|
|
275
|
+
this.addBreadcrumb('http', 'fetch_response', {
|
|
276
|
+
url,
|
|
277
|
+
status: response.status
|
|
278
|
+
});
|
|
279
|
+
return response;
|
|
280
|
+
}).catch(error => {
|
|
281
|
+
this.addBreadcrumb('http', 'fetch_error', {
|
|
282
|
+
url,
|
|
283
|
+
error: error.message
|
|
284
|
+
});
|
|
285
|
+
throw error;
|
|
286
|
+
});
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
289
|
|
|
290
|
-
|
|
290
|
+
/**
|
|
291
291
|
* Capture console logs
|
|
292
292
|
*/
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
293
|
+
setupConsoleCapture() {
|
|
294
|
+
const originalLog = console.log;
|
|
295
|
+
const originalError = console.error;
|
|
296
|
+
const originalWarn = console.warn;
|
|
297
|
+
|
|
298
|
+
console.log = (...args) => {
|
|
299
|
+
this.addBreadcrumb('console', 'log', { message: args.join(' ') });
|
|
300
|
+
originalLog.apply(console, args);
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
console.error = (...args) => {
|
|
304
|
+
this.addBreadcrumb('console', 'error', { message: args.join(' ') });
|
|
305
|
+
originalError.apply(console, args);
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
console.warn = (...args) => {
|
|
309
|
+
this.addBreadcrumb('console', 'warn', { message: args.join(' ') });
|
|
310
|
+
originalWarn.apply(console, args);
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
315
|
* Handle errors - priority: onError callback > fetch > console
|
|
316
316
|
*/
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
// Priority 1: User-defined callback (maximum flexibility)
|
|
322
|
-
if (this.onErrorCallback) {
|
|
323
|
-
try {
|
|
324
|
-
this.onErrorCallback(errorPayload);
|
|
325
|
-
} catch (callbackError) {
|
|
326
|
-
console.warn('SyntropyFront: Error in user callback:', callbackError);
|
|
327
|
-
}
|
|
328
|
-
return;
|
|
329
|
-
}
|
|
317
|
+
handleError(errorPayload) {
|
|
318
|
+
// Default log
|
|
319
|
+
this.logger.error('❌ Error:', errorPayload);
|
|
330
320
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
321
|
+
// Priority 1: User-defined callback (maximum flexibility)
|
|
322
|
+
if (this.onErrorCallback) {
|
|
323
|
+
try {
|
|
324
|
+
this.onErrorCallback(errorPayload);
|
|
325
|
+
} catch (callbackError) {
|
|
326
|
+
console.warn('SyntropyFront: Error in user callback:', callbackError);
|
|
327
|
+
}
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
336
330
|
|
|
337
|
-
|
|
338
|
-
|
|
331
|
+
// Priority 2: Fetch to endpoint
|
|
332
|
+
if (this.fetchConfig) {
|
|
333
|
+
this.postToEndpoint(errorPayload);
|
|
334
|
+
return;
|
|
339
335
|
}
|
|
336
|
+
|
|
337
|
+
// Priority 3: Console only (default)
|
|
338
|
+
// Already logged above
|
|
339
|
+
}
|
|
340
340
|
|
|
341
|
-
|
|
341
|
+
/**
|
|
342
342
|
* Post error object using fetch configuration
|
|
343
343
|
*/
|
|
344
|
-
|
|
345
|
-
|
|
344
|
+
postToEndpoint(errorPayload) {
|
|
345
|
+
const { url, options = {} } = this.fetchConfig;
|
|
346
346
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
const breadcrumb = this.breadcrumbManager.add(category, message, data);
|
|
347
|
+
// Default configuration
|
|
348
|
+
const defaultOptions = {
|
|
349
|
+
method: 'POST',
|
|
350
|
+
headers: {
|
|
351
|
+
'Content-Type': 'application/json',
|
|
352
|
+
...options.headers
|
|
353
|
+
},
|
|
354
|
+
body: JSON.stringify(errorPayload),
|
|
355
|
+
...options
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
fetch(url, defaultOptions).catch(error => {
|
|
359
|
+
console.warn('SyntropyFront: Error posting to endpoint:', error);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Public API
|
|
364
|
+
addBreadcrumb(category, message, data = {}) {
|
|
365
|
+
if (!this.isActive) return;
|
|
368
366
|
|
|
369
|
-
|
|
370
|
-
const breadcrumbs = this.breadcrumbManager.getAll();
|
|
371
|
-
if (breadcrumbs.length > this.maxEvents) {
|
|
372
|
-
this.breadcrumbManager.clear();
|
|
373
|
-
breadcrumbs.slice(-this.maxEvents).forEach(b => this.breadcrumbManager.add(b.category, b.message, b.data));
|
|
374
|
-
}
|
|
367
|
+
const breadcrumb = this.breadcrumbManager.add(category, message, data);
|
|
375
368
|
|
|
376
|
-
|
|
369
|
+
// Keep only the last maxEvents
|
|
370
|
+
const breadcrumbs = this.breadcrumbManager.getAll();
|
|
371
|
+
if (breadcrumbs.length > this.maxEvents) {
|
|
372
|
+
this.breadcrumbManager.clear();
|
|
373
|
+
breadcrumbs.slice(-this.maxEvents).forEach(b => this.breadcrumbManager.add(b.category, b.message, b.data));
|
|
377
374
|
}
|
|
375
|
+
|
|
376
|
+
return breadcrumb;
|
|
377
|
+
}
|
|
378
378
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
379
|
+
getBreadcrumbs() {
|
|
380
|
+
return this.breadcrumbManager.getAll();
|
|
381
|
+
}
|
|
382
382
|
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
383
|
+
clearBreadcrumbs() {
|
|
384
|
+
this.breadcrumbManager.clear();
|
|
385
|
+
}
|
|
386
386
|
|
|
387
|
-
|
|
388
|
-
|
|
387
|
+
sendError(error, context = {}) {
|
|
388
|
+
if (!this.isActive) return;
|
|
389
389
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
390
|
+
const errorData = this.errorManager.send(error, context);
|
|
391
|
+
const errorPayload = {
|
|
392
|
+
...errorData,
|
|
393
|
+
breadcrumbs: this.getBreadcrumbs(),
|
|
394
|
+
timestamp: new Date().toISOString()
|
|
395
|
+
};
|
|
396
396
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
397
|
+
this.handleError(errorPayload);
|
|
398
|
+
return errorData;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
getErrors() {
|
|
402
|
+
return this.errorManager.getAll();
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
clearErrors() {
|
|
406
|
+
this.errorManager.clear();
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Utility methods
|
|
410
|
+
getStats() {
|
|
411
|
+
return {
|
|
412
|
+
breadcrumbs: this.breadcrumbManager.getCount(),
|
|
413
|
+
errors: this.errorManager.getCount(),
|
|
414
|
+
isActive: this.isActive,
|
|
415
|
+
maxEvents: this.maxEvents,
|
|
416
|
+
hasFetchConfig: !!this.fetchConfig,
|
|
417
|
+
hasErrorCallback: !!this.onErrorCallback,
|
|
418
|
+
endpoint: this.fetchConfig?.url || 'console'
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
421
|
}
|
|
422
422
|
|
|
423
423
|
// Single instance - auto-initializes
|