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/dist/react.cjs ADDED
@@ -0,0 +1,391 @@
1
+ 'use strict';
2
+
3
+ var React = require('react');
4
+
5
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
6
+
7
+ var React__default = /*#__PURE__*/_interopDefault(React);
8
+
9
+ /* flarewatch v0.1.0 — https://github.com/seu-usuario/flarewatch */
10
+
11
+
12
+ // src/core/client.ts
13
+ function uid() {
14
+ return `fw-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;
15
+ }
16
+ var SEVERITY_RANK = {
17
+ debug: 0,
18
+ info: 1,
19
+ warning: 2,
20
+ error: 3,
21
+ fatal: 4
22
+ };
23
+ var FlarewatchClient = class {
24
+ constructor(config) {
25
+ this.sessionStart = Date.now();
26
+ this.initialized = false;
27
+ // ─── Listeners globais ─────────────────────────────────────────────────────
28
+ this.onError = (e) => {
29
+ var _a;
30
+ this.capture("error.global", "error", e.message, {
31
+ stack: (_a = e.error) == null ? void 0 : _a.stack,
32
+ filename: e.filename,
33
+ lineno: e.lineno,
34
+ colno: e.colno
35
+ });
36
+ };
37
+ this.onUnhandledRejection = (e) => {
38
+ const err = e.reason instanceof Error ? e.reason : new Error(String(e.reason));
39
+ this.capture("error.promise", "error", err.message, { stack: err.stack });
40
+ };
41
+ this.config = {
42
+ captureGlobalErrors: true,
43
+ captureUnhandledRejections: true,
44
+ capturePerformance: true,
45
+ minLogLevel: "debug",
46
+ defaultContext: {},
47
+ beforeSend: (e) => e,
48
+ debug: false,
49
+ ...config
50
+ };
51
+ }
52
+ // ─── Inicialização ─────────────────────────────────────────────────────────
53
+ init() {
54
+ if (this.initialized) return;
55
+ this.initialized = true;
56
+ if (this.config.captureGlobalErrors) this.attachGlobalErrors();
57
+ if (this.config.captureUnhandledRejections) this.attachUnhandledRejections();
58
+ if (this.config.capturePerformance) this.attachPerformance();
59
+ this.debugLog("flarewatch initialized", this.config);
60
+ }
61
+ destroy() {
62
+ window.removeEventListener("error", this.onError);
63
+ window.removeEventListener("unhandledrejection", this.onUnhandledRejection);
64
+ this.initialized = false;
65
+ }
66
+ // ─── API pública de log ────────────────────────────────────────────────────
67
+ log(message, context) {
68
+ this.capture("log.info", "info", message, context);
69
+ }
70
+ info(message, context) {
71
+ this.capture("log.info", "info", message, context);
72
+ }
73
+ warn(message, context) {
74
+ this.capture("log.warn", "warning", message, context);
75
+ }
76
+ error(message, context) {
77
+ const err = message instanceof Error ? message : new Error(message);
78
+ this.capture("log.error", "error", err.message, { stack: err.stack, ...context });
79
+ }
80
+ debug(message, context) {
81
+ this.capture("log.debug", "debug", message, context);
82
+ }
83
+ // ─── Captura de erro de render (usado pelo ErrorBoundary) ─────────────────
84
+ captureRenderError(error, componentStack) {
85
+ this.capture("error.render", "fatal", error.message, {
86
+ stack: error.stack,
87
+ componentStack
88
+ });
89
+ }
90
+ // ─── Wrapper de fetch ──────────────────────────────────────────────────────
91
+ async fetch(input, init2) {
92
+ var _a, _b;
93
+ const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
94
+ try {
95
+ const res = await globalThis.fetch(input, init2);
96
+ if (!res.ok) {
97
+ this.capture("error.api", res.status >= 500 ? "error" : "warning", `HTTP ${res.status}`, {
98
+ endpoint: url,
99
+ status: res.status,
100
+ statusText: res.statusText,
101
+ method: (_a = init2 == null ? void 0 : init2.method) != null ? _a : "GET"
102
+ });
103
+ }
104
+ return res;
105
+ } catch (err) {
106
+ const error = err instanceof Error ? err : new Error(String(err));
107
+ this.capture("error.api", "error", error.message, {
108
+ endpoint: url,
109
+ method: (_b = init2 == null ? void 0 : init2.method) != null ? _b : "GET",
110
+ stack: error.stack
111
+ });
112
+ throw err;
113
+ }
114
+ }
115
+ // ─── Captura interna ───────────────────────────────────────────────────────
116
+ capture(type, severity, message, context) {
117
+ if (SEVERITY_RANK[severity] < SEVERITY_RANK[this.config.minLogLevel]) return;
118
+ const raw = {
119
+ id: uid(),
120
+ type,
121
+ severity,
122
+ message,
123
+ url: typeof window !== "undefined" ? window.location.href : "",
124
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : "",
125
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
126
+ sessionDuration: Math.round((Date.now() - this.sessionStart) / 1e3),
127
+ context: {
128
+ ...this.config.defaultContext,
129
+ ...context
130
+ }
131
+ };
132
+ const event = this.config.beforeSend(raw);
133
+ if (event === false) {
134
+ this.debugLog("event discarded by beforeSend", raw);
135
+ return;
136
+ }
137
+ this.dispatch(event);
138
+ }
139
+ // ─── Despacho para transports ──────────────────────────────────────────────
140
+ dispatch(event) {
141
+ for (const transport of this.config.transports) {
142
+ try {
143
+ const result = transport.send(event);
144
+ if (result instanceof Promise) {
145
+ result.catch((err) => {
146
+ this.debugLog(`transport "${transport.name}" failed`, err);
147
+ });
148
+ }
149
+ } catch (err) {
150
+ this.debugLog(`transport "${transport.name}" threw`, err);
151
+ }
152
+ }
153
+ }
154
+ attachGlobalErrors() {
155
+ window.addEventListener("error", this.onError);
156
+ }
157
+ attachUnhandledRejections() {
158
+ window.addEventListener("unhandledrejection", this.onUnhandledRejection);
159
+ }
160
+ // ─── Performance (Web Vitals via PerformanceObserver) ─────────────────────
161
+ attachPerformance() {
162
+ if (typeof PerformanceObserver === "undefined") return;
163
+ this.observeMetric("largest-contentful-paint", (entries) => {
164
+ var _a, _b;
165
+ const last = entries[entries.length - 1];
166
+ const value = (_b = (_a = last.renderTime) != null ? _a : last.loadTime) != null ? _b : 0;
167
+ this.capture("perf.lcp", this.lcpSeverity(value), "LCP", { value, unit: "ms" });
168
+ });
169
+ this.observeMetric("layout-shift", (entries) => {
170
+ var _a;
171
+ let cls = 0;
172
+ for (const e of entries) {
173
+ const entry = e;
174
+ if (!entry.hadRecentInput) cls += (_a = entry.value) != null ? _a : 0;
175
+ }
176
+ if (cls > 0) {
177
+ this.capture("perf.cls", this.clsSeverity(cls), "CLS", { value: parseFloat(cls.toFixed(4)), unit: "score" });
178
+ }
179
+ });
180
+ this.observeMetric("first-input", (entries) => {
181
+ var _a;
182
+ const e = entries[0];
183
+ const value = ((_a = e.processingStart) != null ? _a : 0) - e.startTime;
184
+ this.capture("perf.fid", this.fidSeverity(value), "FID", { value: Math.round(value), unit: "ms" });
185
+ });
186
+ this.observePaintAndNav();
187
+ }
188
+ observeMetric(type, cb) {
189
+ try {
190
+ const obs = new PerformanceObserver((list) => cb(list.getEntries()));
191
+ obs.observe({ type, buffered: true });
192
+ } catch (e) {
193
+ }
194
+ }
195
+ observePaintAndNav() {
196
+ try {
197
+ const paintObs = new PerformanceObserver((list) => {
198
+ for (const entry of list.getEntries()) {
199
+ if (entry.name === "first-contentful-paint") {
200
+ this.capture("perf.fcp", this.fcpSeverity(entry.startTime), "FCP", {
201
+ value: Math.round(entry.startTime),
202
+ unit: "ms"
203
+ });
204
+ }
205
+ }
206
+ });
207
+ paintObs.observe({ type: "paint", buffered: true });
208
+ } catch (e) {
209
+ }
210
+ if (typeof window !== "undefined") {
211
+ window.addEventListener("load", () => {
212
+ const nav = performance.getEntriesByType("navigation")[0];
213
+ if (nav) {
214
+ const ttfb = Math.round(nav.responseStart - nav.requestStart);
215
+ this.capture("perf.ttfb", this.ttfbSeverity(ttfb), "TTFB", { value: ttfb, unit: "ms" });
216
+ }
217
+ }, { once: true });
218
+ }
219
+ }
220
+ // ─── Thresholds de severidade (Core Web Vitals) ───────────────────────────
221
+ lcpSeverity(ms) {
222
+ if (ms <= 2500) return "info";
223
+ if (ms <= 4e3) return "warning";
224
+ return "error";
225
+ }
226
+ clsSeverity(score) {
227
+ if (score <= 0.1) return "info";
228
+ if (score <= 0.25) return "warning";
229
+ return "error";
230
+ }
231
+ fidSeverity(ms) {
232
+ if (ms <= 100) return "info";
233
+ if (ms <= 300) return "warning";
234
+ return "error";
235
+ }
236
+ fcpSeverity(ms) {
237
+ if (ms <= 1800) return "info";
238
+ if (ms <= 3e3) return "warning";
239
+ return "error";
240
+ }
241
+ ttfbSeverity(ms) {
242
+ if (ms <= 800) return "info";
243
+ if (ms <= 1800) return "warning";
244
+ return "error";
245
+ }
246
+ // ─── Debug interno ────────────────────────────────────────────────────────
247
+ debugLog(msg, ...args) {
248
+ if (this.config.debug) {
249
+ console.debug(`[flarewatch] ${msg}`, ...args);
250
+ }
251
+ }
252
+ };
253
+
254
+ // src/core/instance.ts
255
+ var instance = null;
256
+ function init(config) {
257
+ if (instance) {
258
+ console.warn("[flarewatch] j\xE1 inicializado. Chame destroy() antes de reinicializar.");
259
+ return instance;
260
+ }
261
+ instance = new FlarewatchClient(config);
262
+ instance.init();
263
+ return instance;
264
+ }
265
+ function getClient() {
266
+ if (!instance) {
267
+ throw new Error(
268
+ "[flarewatch] n\xE3o inicializado. Chame init() antes de usar getClient()."
269
+ );
270
+ }
271
+ return instance;
272
+ }
273
+ function isInitialized() {
274
+ return instance !== null;
275
+ }
276
+
277
+ // src/react/providers.tsx
278
+ var FlarewatchContext = React.createContext(null);
279
+ var FlarewatchProvider = class extends React.Component {
280
+ constructor(props) {
281
+ super(props);
282
+ const client = isInitialized() ? getClient() : init(props.config);
283
+ this.state = { client, crashed: false, lastError: null };
284
+ }
285
+ static getDerivedStateFromError(error) {
286
+ return { crashed: true, lastError: error };
287
+ }
288
+ componentDidCatch(error, info) {
289
+ var _a;
290
+ this.state.client.captureRenderError(error, (_a = info.componentStack) != null ? _a : "");
291
+ }
292
+ componentWillUnmount() {
293
+ }
294
+ render() {
295
+ const { crashed, lastError, client } = this.state;
296
+ const { fallback, children } = this.props;
297
+ if (crashed && lastError) {
298
+ if (typeof fallback === "function") return fallback(lastError);
299
+ if (fallback) return fallback;
300
+ return React__default.default.createElement(DefaultFallback, { error: lastError });
301
+ }
302
+ return React__default.default.createElement(
303
+ FlarewatchContext.Provider,
304
+ { value: client },
305
+ children
306
+ );
307
+ }
308
+ };
309
+ function useFlarewatch() {
310
+ const client = React.useContext(FlarewatchContext);
311
+ if (!client) {
312
+ throw new Error(
313
+ "[flarewatch] useFlarewatch deve ser usado dentro de <FlarewatchProvider>."
314
+ );
315
+ }
316
+ return client;
317
+ }
318
+ function useFlarewatchFetch() {
319
+ const client = useFlarewatch();
320
+ return (input, init2) => client.fetch(input, init2);
321
+ }
322
+ var ErrorBoundary = class extends React.Component {
323
+ constructor() {
324
+ super(...arguments);
325
+ this.state = { crashed: false, error: null };
326
+ }
327
+ static getDerivedStateFromError(error) {
328
+ return { crashed: true, error };
329
+ }
330
+ componentDidCatch(error, info) {
331
+ var _a;
332
+ if (isInitialized()) {
333
+ getClient().captureRenderError(error, (_a = info.componentStack) != null ? _a : "");
334
+ }
335
+ }
336
+ render() {
337
+ const { crashed, error } = this.state;
338
+ const { fallback, children } = this.props;
339
+ if (crashed && error) {
340
+ if (typeof fallback === "function") return fallback(error);
341
+ if (fallback) return fallback;
342
+ return React__default.default.createElement(DefaultFallback, { error });
343
+ }
344
+ return children;
345
+ }
346
+ };
347
+ function DefaultFallback({ error }) {
348
+ return React__default.default.createElement(
349
+ "div",
350
+ {
351
+ style: {
352
+ display: "flex",
353
+ flexDirection: "column",
354
+ alignItems: "center",
355
+ justifyContent: "center",
356
+ minHeight: "200px",
357
+ padding: "32px",
358
+ fontFamily: "system-ui, sans-serif",
359
+ gap: "12px",
360
+ textAlign: "center"
361
+ }
362
+ },
363
+ React__default.default.createElement("strong", { style: { fontSize: "18px" } }, "Algo deu errado"),
364
+ React__default.default.createElement(
365
+ "p",
366
+ { style: { color: "#666", fontSize: "14px", maxWidth: "400px" } },
367
+ error.message
368
+ ),
369
+ React__default.default.createElement(
370
+ "button",
371
+ {
372
+ onClick: () => window.location.reload(),
373
+ style: {
374
+ padding: "8px 20px",
375
+ borderRadius: "6px",
376
+ border: "1px solid #ccc",
377
+ cursor: "pointer",
378
+ fontSize: "14px"
379
+ }
380
+ },
381
+ "Recarregar p\xE1gina"
382
+ )
383
+ );
384
+ }
385
+
386
+ exports.ErrorBoundary = ErrorBoundary;
387
+ exports.FlarewatchProvider = FlarewatchProvider;
388
+ exports.useFlarewatch = useFlarewatch;
389
+ exports.useFlarewatchFetch = useFlarewatchFetch;
390
+ //# sourceMappingURL=react.cjs.map
391
+ //# sourceMappingURL=react.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/client.ts","../src/core/instance.ts","../src/react/providers.tsx"],"names":["init","createContext","Component","React","useContext"],"mappings":"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","file":"react.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 React, {\n Component,\n createContext,\n useContext,\n type ReactNode,\n type ErrorInfo,\n} from \"react\";\nimport { FlarewatchClient } from \"../core/client\";\nimport { init, getClient, isInitialized } from \"../core/instance\";\nimport type { FlarewatchConfig } from \"../types\";\n\n// ─── Context ──────────────────────────────────────────────────────────────────\n\nconst FlarewatchContext = createContext<FlarewatchClient | null>(null);\n\n// ─── Provider ─────────────────────────────────────────────────────────────────\n\nexport interface FlarewatchProviderProps {\n config: FlarewatchConfig;\n children: ReactNode;\n /** Componente de fallback quando ocorre erro de render. */\n fallback?: ReactNode | ((error: Error) => ReactNode);\n}\n\ninterface ProviderState {\n client: FlarewatchClient;\n crashed: boolean;\n lastError: Error | null;\n}\n\nexport class FlarewatchProvider extends Component<FlarewatchProviderProps, ProviderState> {\n constructor(props: FlarewatchProviderProps) {\n super(props);\n const client = isInitialized() ? getClient() : init(props.config);\n this.state = { client, crashed: false, lastError: null };\n }\n\n static getDerivedStateFromError(error: Error): Partial<ProviderState> {\n return { crashed: true, lastError: error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n this.state.client.captureRenderError(error, info.componentStack ?? \"\");\n }\n\n componentWillUnmount(): void {\n // não destroi automaticamente — o dev controla o ciclo de vida\n }\n\n render(): ReactNode {\n const { crashed, lastError, client } = this.state;\n const { fallback, children } = this.props;\n\n if (crashed && lastError) {\n if (typeof fallback === \"function\") return fallback(lastError);\n if (fallback) return fallback;\n return React.createElement(DefaultFallback, { error: lastError });\n }\n\n return React.createElement(\n FlarewatchContext.Provider,\n { value: client },\n children\n );\n }\n}\n\n// ─── Hook principal ───────────────────────────────────────────────────────────\n\n/**\n * Retorna o cliente flarewatch para uso dentro do Provider.\n *\n * @example\n * ```tsx\n * const fw = useFlarewatch();\n * fw.info(\"Usuário fez login\", { userId: \"123\" });\n * ```\n */\nexport function useFlarewatch(): FlarewatchClient {\n const client = useContext(FlarewatchContext);\n if (!client) {\n throw new Error(\n \"[flarewatch] useFlarewatch deve ser usado dentro de <FlarewatchProvider>.\"\n );\n }\n return client;\n}\n\n/**\n * Retorna um wrapper de fetch que captura erros de API automaticamente.\n *\n * @example\n * ```tsx\n * const apiFetch = useFlarewatchFetch();\n * const res = await apiFetch(\"/api/users\");\n * ```\n */\nexport function useFlarewatchFetch(): typeof fetch {\n const client = useFlarewatch();\n return (input, init) => client.fetch(input as RequestInfo, init);\n}\n\n// ─── ErrorBoundary standalone (sem Provider) ─────────────────────────────────\n\nexport interface ErrorBoundaryProps {\n children: ReactNode;\n fallback?: ReactNode | ((error: Error) => ReactNode);\n}\n\ninterface BoundaryState {\n crashed: boolean;\n error: Error | null;\n}\n\nexport class ErrorBoundary extends Component<ErrorBoundaryProps, BoundaryState> {\n state: BoundaryState = { crashed: false, error: null };\n\n static getDerivedStateFromError(error: Error): BoundaryState {\n return { crashed: true, error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n if (isInitialized()) {\n getClient().captureRenderError(error, info.componentStack ?? \"\");\n }\n }\n\n render(): ReactNode {\n const { crashed, error } = this.state;\n const { fallback, children } = this.props;\n\n if (crashed && error) {\n if (typeof fallback === \"function\") return fallback(error);\n if (fallback) return fallback;\n return React.createElement(DefaultFallback, { error });\n }\n\n return children;\n }\n}\n\n// ─── Fallback padrão ──────────────────────────────────────────────────────────\n\nfunction DefaultFallback({ error }: { error: Error }): React.ReactElement {\n return React.createElement(\n \"div\",\n {\n style: {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n minHeight: \"200px\",\n padding: \"32px\",\n fontFamily: \"system-ui, sans-serif\",\n gap: \"12px\",\n textAlign: \"center\",\n },\n },\n React.createElement(\"strong\", { style: { fontSize: \"18px\" } }, \"Algo deu errado\"),\n React.createElement(\n \"p\",\n { style: { color: \"#666\", fontSize: \"14px\", maxWidth: \"400px\" } },\n error.message\n ),\n React.createElement(\n \"button\",\n {\n onClick: () => window.location.reload(),\n style: {\n padding: \"8px 20px\",\n borderRadius: \"6px\",\n border: \"1px solid #ccc\",\n cursor: \"pointer\",\n fontSize: \"14px\",\n },\n },\n \"Recarregar página\"\n )\n );\n}\n"]}
@@ -0,0 +1,57 @@
1
+ import { Component, ReactNode, ErrorInfo } from 'react';
2
+ import { a as FlarewatchConfig, F as FlarewatchClient } from './client-_6VwqY7U.cjs';
3
+
4
+ interface FlarewatchProviderProps {
5
+ config: FlarewatchConfig;
6
+ children: ReactNode;
7
+ /** Componente de fallback quando ocorre erro de render. */
8
+ fallback?: ReactNode | ((error: Error) => ReactNode);
9
+ }
10
+ interface ProviderState {
11
+ client: FlarewatchClient;
12
+ crashed: boolean;
13
+ lastError: Error | null;
14
+ }
15
+ declare class FlarewatchProvider extends Component<FlarewatchProviderProps, ProviderState> {
16
+ constructor(props: FlarewatchProviderProps);
17
+ static getDerivedStateFromError(error: Error): Partial<ProviderState>;
18
+ componentDidCatch(error: Error, info: ErrorInfo): void;
19
+ componentWillUnmount(): void;
20
+ render(): ReactNode;
21
+ }
22
+ /**
23
+ * Retorna o cliente flarewatch para uso dentro do Provider.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const fw = useFlarewatch();
28
+ * fw.info("Usuário fez login", { userId: "123" });
29
+ * ```
30
+ */
31
+ declare function useFlarewatch(): FlarewatchClient;
32
+ /**
33
+ * Retorna um wrapper de fetch que captura erros de API automaticamente.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * const apiFetch = useFlarewatchFetch();
38
+ * const res = await apiFetch("/api/users");
39
+ * ```
40
+ */
41
+ declare function useFlarewatchFetch(): typeof fetch;
42
+ interface ErrorBoundaryProps {
43
+ children: ReactNode;
44
+ fallback?: ReactNode | ((error: Error) => ReactNode);
45
+ }
46
+ interface BoundaryState {
47
+ crashed: boolean;
48
+ error: Error | null;
49
+ }
50
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, BoundaryState> {
51
+ state: BoundaryState;
52
+ static getDerivedStateFromError(error: Error): BoundaryState;
53
+ componentDidCatch(error: Error, info: ErrorInfo): void;
54
+ render(): ReactNode;
55
+ }
56
+
57
+ export { ErrorBoundary, type ErrorBoundaryProps, FlarewatchProvider, type FlarewatchProviderProps, useFlarewatch, useFlarewatchFetch };
@@ -0,0 +1,57 @@
1
+ import { Component, ReactNode, ErrorInfo } from 'react';
2
+ import { a as FlarewatchConfig, F as FlarewatchClient } from './client-_6VwqY7U.js';
3
+
4
+ interface FlarewatchProviderProps {
5
+ config: FlarewatchConfig;
6
+ children: ReactNode;
7
+ /** Componente de fallback quando ocorre erro de render. */
8
+ fallback?: ReactNode | ((error: Error) => ReactNode);
9
+ }
10
+ interface ProviderState {
11
+ client: FlarewatchClient;
12
+ crashed: boolean;
13
+ lastError: Error | null;
14
+ }
15
+ declare class FlarewatchProvider extends Component<FlarewatchProviderProps, ProviderState> {
16
+ constructor(props: FlarewatchProviderProps);
17
+ static getDerivedStateFromError(error: Error): Partial<ProviderState>;
18
+ componentDidCatch(error: Error, info: ErrorInfo): void;
19
+ componentWillUnmount(): void;
20
+ render(): ReactNode;
21
+ }
22
+ /**
23
+ * Retorna o cliente flarewatch para uso dentro do Provider.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const fw = useFlarewatch();
28
+ * fw.info("Usuário fez login", { userId: "123" });
29
+ * ```
30
+ */
31
+ declare function useFlarewatch(): FlarewatchClient;
32
+ /**
33
+ * Retorna um wrapper de fetch que captura erros de API automaticamente.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * const apiFetch = useFlarewatchFetch();
38
+ * const res = await apiFetch("/api/users");
39
+ * ```
40
+ */
41
+ declare function useFlarewatchFetch(): typeof fetch;
42
+ interface ErrorBoundaryProps {
43
+ children: ReactNode;
44
+ fallback?: ReactNode | ((error: Error) => ReactNode);
45
+ }
46
+ interface BoundaryState {
47
+ crashed: boolean;
48
+ error: Error | null;
49
+ }
50
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, BoundaryState> {
51
+ state: BoundaryState;
52
+ static getDerivedStateFromError(error: Error): BoundaryState;
53
+ componentDidCatch(error: Error, info: ErrorInfo): void;
54
+ render(): ReactNode;
55
+ }
56
+
57
+ export { ErrorBoundary, type ErrorBoundaryProps, FlarewatchProvider, type FlarewatchProviderProps, useFlarewatch, useFlarewatchFetch };