flarewatch 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/README.md +277 -0
- package/dist/client-_6VwqY7U.d.cts +106 -0
- package/dist/client-_6VwqY7U.d.ts +106 -0
- package/dist/index.cjs +421 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +413 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +391 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +57 -0
- package/dist/react.d.ts +57 -0
- package/dist/react.js +382 -0
- package/dist/react.js.map +1 -0
- package/package.json +53 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/* flarewatch v0.1.0 — https://github.com/seu-usuario/flarewatch */
|
|
4
|
+
|
|
5
|
+
// src/core/client.ts
|
|
6
|
+
function uid() {
|
|
7
|
+
return `fw-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
|
|
8
|
+
}
|
|
9
|
+
var SEVERITY_RANK = {
|
|
10
|
+
debug: 0,
|
|
11
|
+
info: 1,
|
|
12
|
+
warning: 2,
|
|
13
|
+
error: 3,
|
|
14
|
+
fatal: 4
|
|
15
|
+
};
|
|
16
|
+
var FlarewatchClient = class {
|
|
17
|
+
constructor(config) {
|
|
18
|
+
this.sessionStart = Date.now();
|
|
19
|
+
this.initialized = false;
|
|
20
|
+
// ─── Listeners globais ─────────────────────────────────────────────────────
|
|
21
|
+
this.onError = (e) => {
|
|
22
|
+
var _a;
|
|
23
|
+
this.capture("error.global", "error", e.message, {
|
|
24
|
+
stack: (_a = e.error) == null ? void 0 : _a.stack,
|
|
25
|
+
filename: e.filename,
|
|
26
|
+
lineno: e.lineno,
|
|
27
|
+
colno: e.colno
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
this.onUnhandledRejection = (e) => {
|
|
31
|
+
const err = e.reason instanceof Error ? e.reason : new Error(String(e.reason));
|
|
32
|
+
this.capture("error.promise", "error", err.message, { stack: err.stack });
|
|
33
|
+
};
|
|
34
|
+
this.config = {
|
|
35
|
+
captureGlobalErrors: true,
|
|
36
|
+
captureUnhandledRejections: true,
|
|
37
|
+
capturePerformance: true,
|
|
38
|
+
minLogLevel: "debug",
|
|
39
|
+
defaultContext: {},
|
|
40
|
+
beforeSend: (e) => e,
|
|
41
|
+
debug: false,
|
|
42
|
+
...config
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
// ─── Inicialização ─────────────────────────────────────────────────────────
|
|
46
|
+
init() {
|
|
47
|
+
if (this.initialized) return;
|
|
48
|
+
this.initialized = true;
|
|
49
|
+
if (this.config.captureGlobalErrors) this.attachGlobalErrors();
|
|
50
|
+
if (this.config.captureUnhandledRejections) this.attachUnhandledRejections();
|
|
51
|
+
if (this.config.capturePerformance) this.attachPerformance();
|
|
52
|
+
this.debugLog("flarewatch initialized", this.config);
|
|
53
|
+
}
|
|
54
|
+
destroy() {
|
|
55
|
+
window.removeEventListener("error", this.onError);
|
|
56
|
+
window.removeEventListener("unhandledrejection", this.onUnhandledRejection);
|
|
57
|
+
this.initialized = false;
|
|
58
|
+
}
|
|
59
|
+
// ─── API pública de log ────────────────────────────────────────────────────
|
|
60
|
+
log(message, context) {
|
|
61
|
+
this.capture("log.info", "info", message, context);
|
|
62
|
+
}
|
|
63
|
+
info(message, context) {
|
|
64
|
+
this.capture("log.info", "info", message, context);
|
|
65
|
+
}
|
|
66
|
+
warn(message, context) {
|
|
67
|
+
this.capture("log.warn", "warning", message, context);
|
|
68
|
+
}
|
|
69
|
+
error(message, context) {
|
|
70
|
+
const err = message instanceof Error ? message : new Error(message);
|
|
71
|
+
this.capture("log.error", "error", err.message, { stack: err.stack, ...context });
|
|
72
|
+
}
|
|
73
|
+
debug(message, context) {
|
|
74
|
+
this.capture("log.debug", "debug", message, context);
|
|
75
|
+
}
|
|
76
|
+
// ─── Captura de erro de render (usado pelo ErrorBoundary) ─────────────────
|
|
77
|
+
captureRenderError(error, componentStack) {
|
|
78
|
+
this.capture("error.render", "fatal", error.message, {
|
|
79
|
+
stack: error.stack,
|
|
80
|
+
componentStack
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// ─── Wrapper de fetch ──────────────────────────────────────────────────────
|
|
84
|
+
async fetch(input, init2) {
|
|
85
|
+
var _a, _b;
|
|
86
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
87
|
+
try {
|
|
88
|
+
const res = await globalThis.fetch(input, init2);
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
this.capture("error.api", res.status >= 500 ? "error" : "warning", `HTTP ${res.status}`, {
|
|
91
|
+
endpoint: url,
|
|
92
|
+
status: res.status,
|
|
93
|
+
statusText: res.statusText,
|
|
94
|
+
method: (_a = init2 == null ? void 0 : init2.method) != null ? _a : "GET"
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
return res;
|
|
98
|
+
} catch (err) {
|
|
99
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
100
|
+
this.capture("error.api", "error", error.message, {
|
|
101
|
+
endpoint: url,
|
|
102
|
+
method: (_b = init2 == null ? void 0 : init2.method) != null ? _b : "GET",
|
|
103
|
+
stack: error.stack
|
|
104
|
+
});
|
|
105
|
+
throw err;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// ─── Captura interna ───────────────────────────────────────────────────────
|
|
109
|
+
capture(type, severity, message, context) {
|
|
110
|
+
if (SEVERITY_RANK[severity] < SEVERITY_RANK[this.config.minLogLevel]) return;
|
|
111
|
+
const raw = {
|
|
112
|
+
id: uid(),
|
|
113
|
+
type,
|
|
114
|
+
severity,
|
|
115
|
+
message,
|
|
116
|
+
url: typeof window !== "undefined" ? window.location.href : "",
|
|
117
|
+
userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "",
|
|
118
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
119
|
+
sessionDuration: Math.round((Date.now() - this.sessionStart) / 1e3),
|
|
120
|
+
context: {
|
|
121
|
+
...this.config.defaultContext,
|
|
122
|
+
...context
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const event = this.config.beforeSend(raw);
|
|
126
|
+
if (event === false) {
|
|
127
|
+
this.debugLog("event discarded by beforeSend", raw);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
this.dispatch(event);
|
|
131
|
+
}
|
|
132
|
+
// ─── Despacho para transports ──────────────────────────────────────────────
|
|
133
|
+
dispatch(event) {
|
|
134
|
+
for (const transport of this.config.transports) {
|
|
135
|
+
try {
|
|
136
|
+
const result = transport.send(event);
|
|
137
|
+
if (result instanceof Promise) {
|
|
138
|
+
result.catch((err) => {
|
|
139
|
+
this.debugLog(`transport "${transport.name}" failed`, err);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
} catch (err) {
|
|
143
|
+
this.debugLog(`transport "${transport.name}" threw`, err);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
attachGlobalErrors() {
|
|
148
|
+
window.addEventListener("error", this.onError);
|
|
149
|
+
}
|
|
150
|
+
attachUnhandledRejections() {
|
|
151
|
+
window.addEventListener("unhandledrejection", this.onUnhandledRejection);
|
|
152
|
+
}
|
|
153
|
+
// ─── Performance (Web Vitals via PerformanceObserver) ─────────────────────
|
|
154
|
+
attachPerformance() {
|
|
155
|
+
if (typeof PerformanceObserver === "undefined") return;
|
|
156
|
+
this.observeMetric("largest-contentful-paint", (entries) => {
|
|
157
|
+
var _a, _b;
|
|
158
|
+
const last = entries[entries.length - 1];
|
|
159
|
+
const value = (_b = (_a = last.renderTime) != null ? _a : last.loadTime) != null ? _b : 0;
|
|
160
|
+
this.capture("perf.lcp", this.lcpSeverity(value), "LCP", { value, unit: "ms" });
|
|
161
|
+
});
|
|
162
|
+
this.observeMetric("layout-shift", (entries) => {
|
|
163
|
+
var _a;
|
|
164
|
+
let cls = 0;
|
|
165
|
+
for (const e of entries) {
|
|
166
|
+
const entry = e;
|
|
167
|
+
if (!entry.hadRecentInput) cls += (_a = entry.value) != null ? _a : 0;
|
|
168
|
+
}
|
|
169
|
+
if (cls > 0) {
|
|
170
|
+
this.capture("perf.cls", this.clsSeverity(cls), "CLS", { value: parseFloat(cls.toFixed(4)), unit: "score" });
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
this.observeMetric("first-input", (entries) => {
|
|
174
|
+
var _a;
|
|
175
|
+
const e = entries[0];
|
|
176
|
+
const value = ((_a = e.processingStart) != null ? _a : 0) - e.startTime;
|
|
177
|
+
this.capture("perf.fid", this.fidSeverity(value), "FID", { value: Math.round(value), unit: "ms" });
|
|
178
|
+
});
|
|
179
|
+
this.observePaintAndNav();
|
|
180
|
+
}
|
|
181
|
+
observeMetric(type, cb) {
|
|
182
|
+
try {
|
|
183
|
+
const obs = new PerformanceObserver((list) => cb(list.getEntries()));
|
|
184
|
+
obs.observe({ type, buffered: true });
|
|
185
|
+
} catch (e) {
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
observePaintAndNav() {
|
|
189
|
+
try {
|
|
190
|
+
const paintObs = new PerformanceObserver((list) => {
|
|
191
|
+
for (const entry of list.getEntries()) {
|
|
192
|
+
if (entry.name === "first-contentful-paint") {
|
|
193
|
+
this.capture("perf.fcp", this.fcpSeverity(entry.startTime), "FCP", {
|
|
194
|
+
value: Math.round(entry.startTime),
|
|
195
|
+
unit: "ms"
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
paintObs.observe({ type: "paint", buffered: true });
|
|
201
|
+
} catch (e) {
|
|
202
|
+
}
|
|
203
|
+
if (typeof window !== "undefined") {
|
|
204
|
+
window.addEventListener("load", () => {
|
|
205
|
+
const nav = performance.getEntriesByType("navigation")[0];
|
|
206
|
+
if (nav) {
|
|
207
|
+
const ttfb = Math.round(nav.responseStart - nav.requestStart);
|
|
208
|
+
this.capture("perf.ttfb", this.ttfbSeverity(ttfb), "TTFB", { value: ttfb, unit: "ms" });
|
|
209
|
+
}
|
|
210
|
+
}, { once: true });
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// ─── Thresholds de severidade (Core Web Vitals) ───────────────────────────
|
|
214
|
+
lcpSeverity(ms) {
|
|
215
|
+
if (ms <= 2500) return "info";
|
|
216
|
+
if (ms <= 4e3) return "warning";
|
|
217
|
+
return "error";
|
|
218
|
+
}
|
|
219
|
+
clsSeverity(score) {
|
|
220
|
+
if (score <= 0.1) return "info";
|
|
221
|
+
if (score <= 0.25) return "warning";
|
|
222
|
+
return "error";
|
|
223
|
+
}
|
|
224
|
+
fidSeverity(ms) {
|
|
225
|
+
if (ms <= 100) return "info";
|
|
226
|
+
if (ms <= 300) return "warning";
|
|
227
|
+
return "error";
|
|
228
|
+
}
|
|
229
|
+
fcpSeverity(ms) {
|
|
230
|
+
if (ms <= 1800) return "info";
|
|
231
|
+
if (ms <= 3e3) return "warning";
|
|
232
|
+
return "error";
|
|
233
|
+
}
|
|
234
|
+
ttfbSeverity(ms) {
|
|
235
|
+
if (ms <= 800) return "info";
|
|
236
|
+
if (ms <= 1800) return "warning";
|
|
237
|
+
return "error";
|
|
238
|
+
}
|
|
239
|
+
// ─── Debug interno ────────────────────────────────────────────────────────
|
|
240
|
+
debugLog(msg, ...args) {
|
|
241
|
+
if (this.config.debug) {
|
|
242
|
+
console.debug(`[flarewatch] ${msg}`, ...args);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
// src/core/instance.ts
|
|
248
|
+
var instance = null;
|
|
249
|
+
function init(config) {
|
|
250
|
+
if (instance) {
|
|
251
|
+
console.warn("[flarewatch] j\xE1 inicializado. Chame destroy() antes de reinicializar.");
|
|
252
|
+
return instance;
|
|
253
|
+
}
|
|
254
|
+
instance = new FlarewatchClient(config);
|
|
255
|
+
instance.init();
|
|
256
|
+
return instance;
|
|
257
|
+
}
|
|
258
|
+
function getClient() {
|
|
259
|
+
if (!instance) {
|
|
260
|
+
throw new Error(
|
|
261
|
+
"[flarewatch] n\xE3o inicializado. Chame init() antes de usar getClient()."
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
return instance;
|
|
265
|
+
}
|
|
266
|
+
function destroy() {
|
|
267
|
+
instance == null ? void 0 : instance.destroy();
|
|
268
|
+
instance = null;
|
|
269
|
+
}
|
|
270
|
+
function isInitialized() {
|
|
271
|
+
return instance !== null;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/transports/http.ts
|
|
275
|
+
var STORAGE_KEY = "__flarewatch_queue";
|
|
276
|
+
function httpTransport(options) {
|
|
277
|
+
const {
|
|
278
|
+
url,
|
|
279
|
+
headers = {},
|
|
280
|
+
batchMs = 2e3,
|
|
281
|
+
batchSize = 20,
|
|
282
|
+
timeout = 8e3,
|
|
283
|
+
retries = 3,
|
|
284
|
+
offlineFallback = true,
|
|
285
|
+
storageKey = STORAGE_KEY
|
|
286
|
+
} = options;
|
|
287
|
+
let queue = [];
|
|
288
|
+
let timer = null;
|
|
289
|
+
async function flush() {
|
|
290
|
+
if (queue.length === 0) return;
|
|
291
|
+
const batch = queue.splice(0, batchSize);
|
|
292
|
+
await sendWithRetry(batch, retries);
|
|
293
|
+
}
|
|
294
|
+
async function sendWithRetry(batch, attempts) {
|
|
295
|
+
for (let i = 0; i < attempts; i++) {
|
|
296
|
+
try {
|
|
297
|
+
const controller = new AbortController();
|
|
298
|
+
const t = setTimeout(() => controller.abort(), timeout);
|
|
299
|
+
const res = await fetch(url, {
|
|
300
|
+
method: "POST",
|
|
301
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
302
|
+
body: JSON.stringify(batch.length === 1 ? batch[0] : batch),
|
|
303
|
+
signal: controller.signal
|
|
304
|
+
});
|
|
305
|
+
clearTimeout(t);
|
|
306
|
+
if (res.ok) {
|
|
307
|
+
if (offlineFallback) drainStorage(storageKey);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (res.status >= 400 && res.status < 500) return;
|
|
311
|
+
} catch (e) {
|
|
312
|
+
const isLast = i === attempts - 1;
|
|
313
|
+
if (isLast && offlineFallback) {
|
|
314
|
+
saveToStorage(storageKey, batch);
|
|
315
|
+
} else if (!isLast) {
|
|
316
|
+
await sleep(500 * 2 ** i);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function schedule() {
|
|
322
|
+
if (batchMs === 0) {
|
|
323
|
+
flush();
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (timer) clearTimeout(timer);
|
|
327
|
+
timer = setTimeout(() => {
|
|
328
|
+
timer = null;
|
|
329
|
+
flush();
|
|
330
|
+
}, batchMs);
|
|
331
|
+
}
|
|
332
|
+
function saveToStorage(key, events) {
|
|
333
|
+
var _a;
|
|
334
|
+
try {
|
|
335
|
+
const existing = JSON.parse((_a = localStorage.getItem(key)) != null ? _a : "[]");
|
|
336
|
+
const merged = [...existing, ...events].slice(-100);
|
|
337
|
+
localStorage.setItem(key, JSON.stringify(merged));
|
|
338
|
+
} catch (e) {
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function drainStorage(key) {
|
|
342
|
+
try {
|
|
343
|
+
const raw = localStorage.getItem(key);
|
|
344
|
+
if (!raw) return;
|
|
345
|
+
const pending = JSON.parse(raw);
|
|
346
|
+
if (!pending.length) return;
|
|
347
|
+
localStorage.removeItem(key);
|
|
348
|
+
fetch(url, {
|
|
349
|
+
method: "POST",
|
|
350
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
351
|
+
body: JSON.stringify(pending)
|
|
352
|
+
}).catch(() => {
|
|
353
|
+
saveToStorage(key, pending);
|
|
354
|
+
});
|
|
355
|
+
} catch (e) {
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (typeof window !== "undefined" && offlineFallback) {
|
|
359
|
+
window.addEventListener("online", () => drainStorage(storageKey), { once: false });
|
|
360
|
+
if (navigator.onLine) drainStorage(storageKey);
|
|
361
|
+
}
|
|
362
|
+
return {
|
|
363
|
+
name: "http",
|
|
364
|
+
send(event) {
|
|
365
|
+
queue.push(event);
|
|
366
|
+
if (queue.length >= batchSize) {
|
|
367
|
+
if (timer) clearTimeout(timer);
|
|
368
|
+
flush();
|
|
369
|
+
} else {
|
|
370
|
+
schedule();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function sleep(ms) {
|
|
376
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/transports/console.ts
|
|
380
|
+
var COLORS = {
|
|
381
|
+
fatal: "background:#7F1D1D;color:#FEF2F2;font-weight:bold;padding:2px 6px;border-radius:3px",
|
|
382
|
+
error: "background:#991B1B;color:#FEF2F2;font-weight:bold;padding:2px 6px;border-radius:3px",
|
|
383
|
+
warning: "background:#92400E;color:#FFFBEB;font-weight:bold;padding:2px 6px;border-radius:3px",
|
|
384
|
+
info: "background:#1E3A5F;color:#EFF6FF;font-weight:bold;padding:2px 6px;border-radius:3px",
|
|
385
|
+
debug: "background:#1F2937;color:#F9FAFB;font-weight:bold;padding:2px 6px;border-radius:3px"
|
|
386
|
+
};
|
|
387
|
+
var SEVERITY_RANK2 = {
|
|
388
|
+
debug: 0,
|
|
389
|
+
info: 1,
|
|
390
|
+
warning: 2,
|
|
391
|
+
error: 3,
|
|
392
|
+
fatal: 4
|
|
393
|
+
};
|
|
394
|
+
function consoleTransport(options = {}) {
|
|
395
|
+
const { minLevel = "debug", verbose = false } = options;
|
|
396
|
+
return {
|
|
397
|
+
name: "console",
|
|
398
|
+
send(event) {
|
|
399
|
+
if (SEVERITY_RANK2[event.severity] < SEVERITY_RANK2[minLevel]) return;
|
|
400
|
+
const label = `[flarewatch] ${event.type}`;
|
|
401
|
+
const style = COLORS[event.severity];
|
|
402
|
+
const msg = event.message;
|
|
403
|
+
const fn = event.severity === "fatal" || event.severity === "error" ? console.error : event.severity === "warning" ? console.warn : event.severity === "debug" ? console.debug : console.info;
|
|
404
|
+
if (verbose) {
|
|
405
|
+
fn(`%c${label}%c ${msg}`, style, "color:inherit", event);
|
|
406
|
+
} else {
|
|
407
|
+
fn(`%c${label}%c ${msg}`, style, "color:inherit");
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
exports.FlarewatchClient = FlarewatchClient;
|
|
414
|
+
exports.consoleTransport = consoleTransport;
|
|
415
|
+
exports.destroy = destroy;
|
|
416
|
+
exports.getClient = getClient;
|
|
417
|
+
exports.httpTransport = httpTransport;
|
|
418
|
+
exports.init = init;
|
|
419
|
+
exports.isInitialized = isInitialized;
|
|
420
|
+
//# sourceMappingURL=index.cjs.map
|
|
421
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/client.ts","../src/core/instance.ts","../src/transports/http.ts","../src/transports/console.ts"],"names":["init","SEVERITY_RANK"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n FlarewatchConfig,\n FlarewatchEvent,\n EventType,\n Severity,\n} from \"../types\";\n\n// ─── Utilitários internos ────────────────────────────────────────────────────\n\nfunction uid(): string {\n return `fw-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;\n}\n\nconst SEVERITY_RANK: Record<Severity, number> = {\n debug: 0,\n info: 1,\n warning: 2,\n error: 3,\n fatal: 4,\n};\n\n// ─── Client ─────────────────────────────────────────────────────────────────\n\nexport class FlarewatchClient {\n private config: Required<FlarewatchConfig>;\n private sessionStart = Date.now();\n private initialized = false;\n\n constructor(config: FlarewatchConfig) {\n this.config = {\n captureGlobalErrors: true,\n captureUnhandledRejections: true,\n capturePerformance: true,\n minLogLevel: \"debug\",\n defaultContext: {},\n beforeSend: (e) => e,\n debug: false,\n ...config,\n };\n }\n\n // ─── Inicialização ─────────────────────────────────────────────────────────\n\n init(): void {\n if (this.initialized) return;\n this.initialized = true;\n\n if (this.config.captureGlobalErrors) this.attachGlobalErrors();\n if (this.config.captureUnhandledRejections) this.attachUnhandledRejections();\n if (this.config.capturePerformance) this.attachPerformance();\n\n this.debugLog(\"flarewatch initialized\", this.config);\n }\n\n destroy(): void {\n window.removeEventListener(\"error\", this.onError);\n window.removeEventListener(\"unhandledrejection\", this.onUnhandledRejection);\n this.initialized = false;\n }\n\n // ─── API pública de log ────────────────────────────────────────────────────\n\n log(message: string, context?: Record<string, unknown>): void {\n this.capture(\"log.info\", \"info\", message, context);\n }\n\n info(message: string, context?: Record<string, unknown>): void {\n this.capture(\"log.info\", \"info\", message, context);\n }\n\n warn(message: string, context?: Record<string, unknown>): void {\n this.capture(\"log.warn\", \"warning\", message, context);\n }\n\n error(message: string | Error, context?: Record<string, unknown>): void {\n const err = message instanceof Error ? message : new Error(message);\n this.capture(\"log.error\", \"error\", err.message, { stack: err.stack, ...context });\n }\n\n debug(message: string, context?: Record<string, unknown>): void {\n this.capture(\"log.debug\", \"debug\", message, context);\n }\n\n // ─── Captura de erro de render (usado pelo ErrorBoundary) ─────────────────\n\n captureRenderError(error: Error, componentStack: string): void {\n this.capture(\"error.render\", \"fatal\", error.message, {\n stack: error.stack,\n componentStack,\n });\n }\n\n // ─── Wrapper de fetch ──────────────────────────────────────────────────────\n\n async fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {\n const url = typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : (input as Request).url;\n\n try {\n const res = await globalThis.fetch(input, init);\n\n if (!res.ok) {\n this.capture(\"error.api\", res.status >= 500 ? \"error\" : \"warning\", `HTTP ${res.status}`, {\n endpoint: url,\n status: res.status,\n statusText: res.statusText,\n method: init?.method ?? \"GET\",\n });\n }\n\n return res;\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n this.capture(\"error.api\", \"error\", error.message, {\n endpoint: url,\n method: init?.method ?? \"GET\",\n stack: error.stack,\n });\n throw err;\n }\n }\n\n // ─── Captura interna ───────────────────────────────────────────────────────\n\n capture(\n type: EventType,\n severity: Severity,\n message: string,\n context?: Record<string, unknown>\n ): void {\n if (SEVERITY_RANK[severity] < SEVERITY_RANK[this.config.minLogLevel]) return;\n\n const raw: FlarewatchEvent = {\n id: uid(),\n type,\n severity,\n message,\n url: typeof window !== \"undefined\" ? window.location.href : \"\",\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"\",\n timestamp: new Date().toISOString(),\n sessionDuration: Math.round((Date.now() - this.sessionStart) / 1000),\n context: {\n ...this.config.defaultContext,\n ...context,\n },\n };\n\n const event = this.config.beforeSend(raw);\n if (event === false) {\n this.debugLog(\"event discarded by beforeSend\", raw);\n return;\n }\n\n this.dispatch(event);\n }\n\n // ─── Despacho para transports ──────────────────────────────────────────────\n\n private dispatch(event: FlarewatchEvent): void {\n for (const transport of this.config.transports) {\n try {\n const result = transport.send(event);\n if (result instanceof Promise) {\n result.catch((err) => {\n this.debugLog(`transport \"${transport.name}\" failed`, err);\n });\n }\n } catch (err) {\n this.debugLog(`transport \"${transport.name}\" threw`, err);\n }\n }\n }\n\n // ─── Listeners globais ─────────────────────────────────────────────────────\n\n private onError = (e: ErrorEvent): void => {\n this.capture(\"error.global\", \"error\", e.message, {\n stack: e.error?.stack,\n filename: e.filename,\n lineno: e.lineno,\n colno: e.colno,\n });\n };\n\n private onUnhandledRejection = (e: PromiseRejectionEvent): void => {\n const err = e.reason instanceof Error ? e.reason : new Error(String(e.reason));\n this.capture(\"error.promise\", \"error\", err.message, { stack: err.stack });\n };\n\n private attachGlobalErrors(): void {\n window.addEventListener(\"error\", this.onError);\n }\n\n private attachUnhandledRejections(): void {\n window.addEventListener(\"unhandledrejection\", this.onUnhandledRejection);\n }\n\n // ─── Performance (Web Vitals via PerformanceObserver) ─────────────────────\n\n private attachPerformance(): void {\n if (typeof PerformanceObserver === \"undefined\") return;\n\n // LCP\n this.observeMetric(\"largest-contentful-paint\", (entries) => {\n const last = entries[entries.length - 1] as PerformanceEntry & { renderTime?: number; loadTime?: number };\n const value = last.renderTime ?? last.loadTime ?? 0;\n this.capture(\"perf.lcp\", this.lcpSeverity(value), \"LCP\", { value, unit: \"ms\" });\n });\n\n // CLS\n this.observeMetric(\"layout-shift\", (entries) => {\n let cls = 0;\n for (const e of entries) {\n const entry = e as PerformanceEntry & { hadRecentInput?: boolean; value?: number };\n if (!entry.hadRecentInput) cls += entry.value ?? 0;\n }\n if (cls > 0) {\n this.capture(\"perf.cls\", this.clsSeverity(cls), \"CLS\", { value: parseFloat(cls.toFixed(4)), unit: \"score\" });\n }\n });\n\n // FID\n this.observeMetric(\"first-input\", (entries) => {\n const e = entries[0] as PerformanceEntry & { processingStart?: number };\n const value = (e.processingStart ?? 0) - e.startTime;\n this.capture(\"perf.fid\", this.fidSeverity(value), \"FID\", { value: Math.round(value), unit: \"ms\" });\n });\n\n // FCP + TTFB via navigation\n this.observePaintAndNav();\n }\n\n private observeMetric(type: string, cb: (entries: PerformanceEntry[]) => void): void {\n try {\n const obs = new PerformanceObserver((list) => cb(list.getEntries()));\n obs.observe({ type, buffered: true });\n } catch {\n // métrica não suportada no browser — silencia\n }\n }\n\n private observePaintAndNav(): void {\n try {\n // FCP\n const paintObs = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) {\n if (entry.name === \"first-contentful-paint\") {\n this.capture(\"perf.fcp\", this.fcpSeverity(entry.startTime), \"FCP\", {\n value: Math.round(entry.startTime),\n unit: \"ms\",\n });\n }\n }\n });\n paintObs.observe({ type: \"paint\", buffered: true });\n } catch { /* não suportado */ }\n\n // TTFB via navigation timing\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"load\", () => {\n const nav = performance.getEntriesByType(\"navigation\")[0] as PerformanceNavigationTiming | undefined;\n if (nav) {\n const ttfb = Math.round(nav.responseStart - nav.requestStart);\n this.capture(\"perf.ttfb\", this.ttfbSeverity(ttfb), \"TTFB\", { value: ttfb, unit: \"ms\" });\n }\n }, { once: true });\n }\n }\n\n // ─── Thresholds de severidade (Core Web Vitals) ───────────────────────────\n\n private lcpSeverity(ms: number): Severity {\n if (ms <= 2500) return \"info\";\n if (ms <= 4000) return \"warning\";\n return \"error\";\n }\n\n private clsSeverity(score: number): Severity {\n if (score <= 0.1) return \"info\";\n if (score <= 0.25) return \"warning\";\n return \"error\";\n }\n\n private fidSeverity(ms: number): Severity {\n if (ms <= 100) return \"info\";\n if (ms <= 300) return \"warning\";\n return \"error\";\n }\n\n private fcpSeverity(ms: number): Severity {\n if (ms <= 1800) return \"info\";\n if (ms <= 3000) return \"warning\";\n return \"error\";\n }\n\n private ttfbSeverity(ms: number): Severity {\n if (ms <= 800) return \"info\";\n if (ms <= 1800) return \"warning\";\n return \"error\";\n }\n\n // ─── Debug interno ────────────────────────────────────────────────────────\n\n private debugLog(msg: string, ...args: unknown[]): void {\n if (this.config.debug) {\n console.debug(`[flarewatch] ${msg}`, ...args);\n }\n }\n}\n","import { FlarewatchClient } from \"./client\";\nimport type { FlarewatchConfig } from \"../types\";\n\nlet instance: FlarewatchClient | null = null;\n\n/**\n * Inicializa o flarewatch. Chame uma vez no entry point da aplicação.\n *\n * @example\n * ```ts\n * import { init, httpTransport } from \"flarewatch\";\n *\n * init({\n * transports: [httpTransport({ url: \"/api/errors\" })],\n * });\n * ```\n */\nexport function init(config: FlarewatchConfig): FlarewatchClient {\n if (instance) {\n console.warn(\"[flarewatch] já inicializado. Chame destroy() antes de reinicializar.\");\n return instance;\n }\n instance = new FlarewatchClient(config);\n instance.init();\n return instance;\n}\n\n/**\n * Retorna a instância atual. Lança se não inicializado.\n */\nexport function getClient(): FlarewatchClient {\n if (!instance) {\n throw new Error(\n \"[flarewatch] não inicializado. Chame init() antes de usar getClient().\"\n );\n }\n return instance;\n}\n\n/**\n * Destrói a instância atual (útil em testes ou hot-reload).\n */\nexport function destroy(): void {\n instance?.destroy();\n instance = null;\n}\n\n/**\n * true se o flarewatch já foi inicializado.\n */\nexport function isInitialized(): boolean {\n return instance !== null;\n}\n","import type { Transport, FlarewatchEvent } from \"../types\";\n\nexport interface HttpTransportOptions {\n /** URL do endpoint que recebe os eventos */\n url: string;\n /**\n * Headers adicionais (ex: Authorization).\n * @default {}\n */\n headers?: Record<string, string>;\n /**\n * Enviar eventos em batch após X ms de debounce.\n * 0 = envio imediato por evento.\n * @default 2000\n */\n batchMs?: number;\n /**\n * Tamanho máximo do batch antes de forçar envio.\n * @default 20\n */\n batchSize?: number;\n /**\n * Timeout da requisição em ms.\n * @default 8000\n */\n timeout?: number;\n /**\n * Quantas vezes tentar reenviar em caso de falha.\n * @default 3\n */\n retries?: number;\n /**\n * Salvar eventos no localStorage quando offline e reenviar depois.\n * @default true\n */\n offlineFallback?: boolean;\n /**\n * Chave usada no localStorage para eventos pendentes.\n * @default \"__flarewatch_queue\"\n */\n storageKey?: string;\n}\n\nconst STORAGE_KEY = \"__flarewatch_queue\";\n\nexport function httpTransport(options: HttpTransportOptions): Transport {\n const {\n url,\n headers = {},\n batchMs = 2000,\n batchSize = 20,\n timeout = 8000,\n retries = 3,\n offlineFallback = true,\n storageKey = STORAGE_KEY,\n } = options;\n\n let queue: FlarewatchEvent[] = [];\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Envio da fila ────────────────────────────────────────────────────────\n\n async function flush(): Promise<void> {\n if (queue.length === 0) return;\n const batch = queue.splice(0, batchSize);\n await sendWithRetry(batch, retries);\n }\n\n async function sendWithRetry(batch: FlarewatchEvent[], attempts: number): Promise<void> {\n for (let i = 0; i < attempts; i++) {\n try {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), timeout);\n\n const res = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(batch.length === 1 ? batch[0] : batch),\n signal: controller.signal,\n });\n\n clearTimeout(t);\n\n if (res.ok) {\n // limpa da fila offline se havia eventos salvos\n if (offlineFallback) drainStorage(storageKey);\n return;\n }\n\n // 4xx não adianta retry\n if (res.status >= 400 && res.status < 500) return;\n\n } catch {\n const isLast = i === attempts - 1;\n if (isLast && offlineFallback) {\n saveToStorage(storageKey, batch);\n } else if (!isLast) {\n await sleep(500 * 2 ** i); // backoff exponencial: 500ms, 1s, 2s\n }\n }\n }\n }\n\n function schedule(): void {\n if (batchMs === 0) {\n flush();\n return;\n }\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n timer = null;\n flush();\n }, batchMs);\n }\n\n // ─── Fila offline ─────────────────────────────────────────────────────────\n\n function saveToStorage(key: string, events: FlarewatchEvent[]): void {\n try {\n const existing: FlarewatchEvent[] = JSON.parse(localStorage.getItem(key) ?? \"[]\");\n const merged = [...existing, ...events].slice(-100); // max 100 eventos\n localStorage.setItem(key, JSON.stringify(merged));\n } catch { /* localStorage indisponível */ }\n }\n\n function drainStorage(key: string): void {\n try {\n const raw = localStorage.getItem(key);\n if (!raw) return;\n const pending: FlarewatchEvent[] = JSON.parse(raw);\n if (!pending.length) return;\n localStorage.removeItem(key);\n // reenvia sem retry para não criar loop\n fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...headers },\n body: JSON.stringify(pending),\n }).catch(() => {\n // se falhar de novo, salva de volta\n saveToStorage(key, pending);\n });\n } catch { /* ignora */ }\n }\n\n // drena na inicialização (caso haja eventos salvos de sessão anterior)\n if (typeof window !== \"undefined\" && offlineFallback) {\n window.addEventListener(\"online\", () => drainStorage(storageKey), { once: false });\n // tenta drenar imediatamente se já estiver online\n if (navigator.onLine) drainStorage(storageKey);\n }\n\n // ─── Transport ────────────────────────────────────────────────────────────\n\n return {\n name: \"http\",\n send(event: FlarewatchEvent): void {\n queue.push(event);\n if (queue.length >= batchSize) {\n if (timer) clearTimeout(timer);\n flush();\n } else {\n schedule();\n }\n },\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n","import type { Transport, FlarewatchEvent, Severity } from \"../types\";\n\nexport interface ConsoleTransportOptions {\n /**\n * Nível mínimo para exibir no console.\n * @default \"debug\"\n */\n minLevel?: Severity;\n /**\n * Exibe o objeto completo do evento abaixo da mensagem.\n * @default false\n */\n verbose?: boolean;\n}\n\nconst COLORS: Record<Severity, string> = {\n fatal: \"background:#7F1D1D;color:#FEF2F2;font-weight:bold;padding:2px 6px;border-radius:3px\",\n error: \"background:#991B1B;color:#FEF2F2;font-weight:bold;padding:2px 6px;border-radius:3px\",\n warning: \"background:#92400E;color:#FFFBEB;font-weight:bold;padding:2px 6px;border-radius:3px\",\n info: \"background:#1E3A5F;color:#EFF6FF;font-weight:bold;padding:2px 6px;border-radius:3px\",\n debug: \"background:#1F2937;color:#F9FAFB;font-weight:bold;padding:2px 6px;border-radius:3px\",\n};\n\nconst SEVERITY_RANK: Record<Severity, number> = {\n debug: 0, info: 1, warning: 2, error: 3, fatal: 4,\n};\n\nexport function consoleTransport(options: ConsoleTransportOptions = {}): Transport {\n const { minLevel = \"debug\", verbose = false } = options;\n\n return {\n name: \"console\",\n send(event: FlarewatchEvent): void {\n if (SEVERITY_RANK[event.severity] < SEVERITY_RANK[minLevel]) return;\n\n const label = `[flarewatch] ${event.type}`;\n const style = COLORS[event.severity];\n const msg = event.message;\n\n const fn = event.severity === \"fatal\" || event.severity === \"error\"\n ? console.error\n : event.severity === \"warning\"\n ? console.warn\n : event.severity === \"debug\"\n ? console.debug\n : console.info;\n\n if (verbose) {\n fn(`%c${label}%c ${msg}`, style, \"color:inherit\", event);\n } else {\n fn(`%c${label}%c ${msg}`, style, \"color:inherit\");\n }\n },\n };\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { F as FlarewatchClient, a as FlarewatchConfig, T as Transport, S as Severity } from './client-_6VwqY7U.cjs';
|
|
2
|
+
export { E as EventType, b as FlarewatchEvent } from './client-_6VwqY7U.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Inicializa o flarewatch. Chame uma vez no entry point da aplicação.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { init, httpTransport } from "flarewatch";
|
|
10
|
+
*
|
|
11
|
+
* init({
|
|
12
|
+
* transports: [httpTransport({ url: "/api/errors" })],
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare function init(config: FlarewatchConfig): FlarewatchClient;
|
|
17
|
+
/**
|
|
18
|
+
* Retorna a instância atual. Lança se não inicializado.
|
|
19
|
+
*/
|
|
20
|
+
declare function getClient(): FlarewatchClient;
|
|
21
|
+
/**
|
|
22
|
+
* Destrói a instância atual (útil em testes ou hot-reload).
|
|
23
|
+
*/
|
|
24
|
+
declare function destroy(): void;
|
|
25
|
+
/**
|
|
26
|
+
* true se o flarewatch já foi inicializado.
|
|
27
|
+
*/
|
|
28
|
+
declare function isInitialized(): boolean;
|
|
29
|
+
|
|
30
|
+
interface HttpTransportOptions {
|
|
31
|
+
/** URL do endpoint que recebe os eventos */
|
|
32
|
+
url: string;
|
|
33
|
+
/**
|
|
34
|
+
* Headers adicionais (ex: Authorization).
|
|
35
|
+
* @default {}
|
|
36
|
+
*/
|
|
37
|
+
headers?: Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Enviar eventos em batch após X ms de debounce.
|
|
40
|
+
* 0 = envio imediato por evento.
|
|
41
|
+
* @default 2000
|
|
42
|
+
*/
|
|
43
|
+
batchMs?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Tamanho máximo do batch antes de forçar envio.
|
|
46
|
+
* @default 20
|
|
47
|
+
*/
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Timeout da requisição em ms.
|
|
51
|
+
* @default 8000
|
|
52
|
+
*/
|
|
53
|
+
timeout?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Quantas vezes tentar reenviar em caso de falha.
|
|
56
|
+
* @default 3
|
|
57
|
+
*/
|
|
58
|
+
retries?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Salvar eventos no localStorage quando offline e reenviar depois.
|
|
61
|
+
* @default true
|
|
62
|
+
*/
|
|
63
|
+
offlineFallback?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Chave usada no localStorage para eventos pendentes.
|
|
66
|
+
* @default "__flarewatch_queue"
|
|
67
|
+
*/
|
|
68
|
+
storageKey?: string;
|
|
69
|
+
}
|
|
70
|
+
declare function httpTransport(options: HttpTransportOptions): Transport;
|
|
71
|
+
|
|
72
|
+
interface ConsoleTransportOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Nível mínimo para exibir no console.
|
|
75
|
+
* @default "debug"
|
|
76
|
+
*/
|
|
77
|
+
minLevel?: Severity;
|
|
78
|
+
/**
|
|
79
|
+
* Exibe o objeto completo do evento abaixo da mensagem.
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
verbose?: boolean;
|
|
83
|
+
}
|
|
84
|
+
declare function consoleTransport(options?: ConsoleTransportOptions): Transport;
|
|
85
|
+
|
|
86
|
+
export { type ConsoleTransportOptions, FlarewatchClient, FlarewatchConfig, type HttpTransportOptions, Severity, Transport, consoleTransport, destroy, getClient, httpTransport, init, isInitialized };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { F as FlarewatchClient, a as FlarewatchConfig, T as Transport, S as Severity } from './client-_6VwqY7U.js';
|
|
2
|
+
export { E as EventType, b as FlarewatchEvent } from './client-_6VwqY7U.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Inicializa o flarewatch. Chame uma vez no entry point da aplicação.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { init, httpTransport } from "flarewatch";
|
|
10
|
+
*
|
|
11
|
+
* init({
|
|
12
|
+
* transports: [httpTransport({ url: "/api/errors" })],
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare function init(config: FlarewatchConfig): FlarewatchClient;
|
|
17
|
+
/**
|
|
18
|
+
* Retorna a instância atual. Lança se não inicializado.
|
|
19
|
+
*/
|
|
20
|
+
declare function getClient(): FlarewatchClient;
|
|
21
|
+
/**
|
|
22
|
+
* Destrói a instância atual (útil em testes ou hot-reload).
|
|
23
|
+
*/
|
|
24
|
+
declare function destroy(): void;
|
|
25
|
+
/**
|
|
26
|
+
* true se o flarewatch já foi inicializado.
|
|
27
|
+
*/
|
|
28
|
+
declare function isInitialized(): boolean;
|
|
29
|
+
|
|
30
|
+
interface HttpTransportOptions {
|
|
31
|
+
/** URL do endpoint que recebe os eventos */
|
|
32
|
+
url: string;
|
|
33
|
+
/**
|
|
34
|
+
* Headers adicionais (ex: Authorization).
|
|
35
|
+
* @default {}
|
|
36
|
+
*/
|
|
37
|
+
headers?: Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* Enviar eventos em batch após X ms de debounce.
|
|
40
|
+
* 0 = envio imediato por evento.
|
|
41
|
+
* @default 2000
|
|
42
|
+
*/
|
|
43
|
+
batchMs?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Tamanho máximo do batch antes de forçar envio.
|
|
46
|
+
* @default 20
|
|
47
|
+
*/
|
|
48
|
+
batchSize?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Timeout da requisição em ms.
|
|
51
|
+
* @default 8000
|
|
52
|
+
*/
|
|
53
|
+
timeout?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Quantas vezes tentar reenviar em caso de falha.
|
|
56
|
+
* @default 3
|
|
57
|
+
*/
|
|
58
|
+
retries?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Salvar eventos no localStorage quando offline e reenviar depois.
|
|
61
|
+
* @default true
|
|
62
|
+
*/
|
|
63
|
+
offlineFallback?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Chave usada no localStorage para eventos pendentes.
|
|
66
|
+
* @default "__flarewatch_queue"
|
|
67
|
+
*/
|
|
68
|
+
storageKey?: string;
|
|
69
|
+
}
|
|
70
|
+
declare function httpTransport(options: HttpTransportOptions): Transport;
|
|
71
|
+
|
|
72
|
+
interface ConsoleTransportOptions {
|
|
73
|
+
/**
|
|
74
|
+
* Nível mínimo para exibir no console.
|
|
75
|
+
* @default "debug"
|
|
76
|
+
*/
|
|
77
|
+
minLevel?: Severity;
|
|
78
|
+
/**
|
|
79
|
+
* Exibe o objeto completo do evento abaixo da mensagem.
|
|
80
|
+
* @default false
|
|
81
|
+
*/
|
|
82
|
+
verbose?: boolean;
|
|
83
|
+
}
|
|
84
|
+
declare function consoleTransport(options?: ConsoleTransportOptions): Transport;
|
|
85
|
+
|
|
86
|
+
export { type ConsoleTransportOptions, FlarewatchClient, FlarewatchConfig, type HttpTransportOptions, Severity, Transport, consoleTransport, destroy, getClient, httpTransport, init, isInitialized };
|