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