@backtrack-js/browser 0.5.1 → 0.5.2
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 +30 -483
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +628 -607
- package/dist/index.js.map +1 -1
- package/dist/storage/db.d.ts.map +1 -1
- package/dist/types/incident.d.ts +1 -0
- package/dist/types/incident.d.ts.map +1 -1
- package/dist/viewer/assets/index-092olPra.css +1 -0
- package/dist/viewer/assets/index-D8m3bwRf.js +197 -0
- package/dist/viewer/index.html +2 -2
- package/dist/widget/widget.d.ts.map +1 -1
- package/package.json +3 -1
- package/dist/viewer/assets/index-C3SZvpLL.js +0 -197
- package/dist/viewer/assets/index-CKVr0pQ5.css +0 -1
package/dist/index.js
CHANGED
|
@@ -63,9 +63,9 @@ class Bt {
|
|
|
63
63
|
if (!this.idbFactory)
|
|
64
64
|
throw new Error("IndexedDB não está disponível neste ambiente.");
|
|
65
65
|
return new Promise((t, e) => {
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
const i =
|
|
66
|
+
const r = this.idbFactory.open(this.dbName, At);
|
|
67
|
+
r.onupgradeneeded = (n) => {
|
|
68
|
+
const i = n.target.result;
|
|
69
69
|
if (i.objectStoreNames.contains(O) || i.createObjectStore(O, { keyPath: "id" }).createIndex("startedAt", "startedAt", { unique: !1 }), !i.objectStoreNames.contains(T)) {
|
|
70
70
|
const a = i.createObjectStore(T, { keyPath: "id" });
|
|
71
71
|
a.createIndex("sessionId", "sessionId", { unique: !1 }), a.createIndex("tabId", "tabId", { unique: !1 }), a.createIndex("sequence", "sequence", { unique: !1 }), a.createIndex("startedAt", "startedAt", { unique: !1 }), a.createIndex("endedAt", "endedAt", { unique: !1 });
|
|
@@ -74,10 +74,10 @@ class Bt {
|
|
|
74
74
|
const a = i.createObjectStore(R, { keyPath: "id" });
|
|
75
75
|
a.createIndex("sessionId", "sessionId", { unique: !1 }), a.createIndex("state", "state", { unique: !1 }), a.createIndex("triggeredAt", "triggeredAt", { unique: !1 });
|
|
76
76
|
}
|
|
77
|
-
},
|
|
78
|
-
this.db =
|
|
79
|
-
},
|
|
80
|
-
e(
|
|
77
|
+
}, r.onsuccess = (n) => {
|
|
78
|
+
this.db = n.target.result, t(this.db);
|
|
79
|
+
}, r.onerror = (n) => {
|
|
80
|
+
e(n.target.error);
|
|
81
81
|
};
|
|
82
82
|
});
|
|
83
83
|
}
|
|
@@ -87,117 +87,118 @@ class Bt {
|
|
|
87
87
|
// --- SESSIONS ---
|
|
88
88
|
async putSession(t) {
|
|
89
89
|
const e = await this.open();
|
|
90
|
-
return new Promise((
|
|
90
|
+
return new Promise((r, n) => {
|
|
91
91
|
const i = e.transaction(O, "readwrite");
|
|
92
|
-
i.objectStore(O).put(t), i.oncomplete = () =>
|
|
92
|
+
i.objectStore(O).put(t), i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
93
93
|
});
|
|
94
94
|
}
|
|
95
95
|
async getSession(t) {
|
|
96
96
|
const e = await this.open();
|
|
97
|
-
return new Promise((
|
|
97
|
+
return new Promise((r, n) => {
|
|
98
98
|
const a = e.transaction(O, "readonly").objectStore(O).get(t);
|
|
99
|
-
a.onsuccess = () =>
|
|
99
|
+
a.onsuccess = () => r(a.result || null), a.onerror = () => n(a.error);
|
|
100
100
|
});
|
|
101
101
|
}
|
|
102
102
|
// --- CHUNKS ---
|
|
103
103
|
async putChunk(t) {
|
|
104
104
|
const e = await this.open();
|
|
105
|
-
return new Promise((
|
|
105
|
+
return new Promise((r, n) => {
|
|
106
106
|
const i = e.transaction(T, "readwrite");
|
|
107
|
-
i.objectStore(T).put(t), i.oncomplete = () =>
|
|
107
|
+
i.objectStore(T).put(t), i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
110
|
async putChunks(t) {
|
|
111
111
|
if (t.length === 0) return;
|
|
112
112
|
const e = await this.open();
|
|
113
|
-
return new Promise((
|
|
113
|
+
return new Promise((r, n) => {
|
|
114
114
|
const i = e.transaction(T, "readwrite"), a = i.objectStore(T);
|
|
115
115
|
for (const s of t)
|
|
116
116
|
a.put(s);
|
|
117
|
-
i.oncomplete = () =>
|
|
117
|
+
i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
async getChunk(t) {
|
|
121
121
|
const e = await this.open();
|
|
122
|
-
return new Promise((
|
|
122
|
+
return new Promise((r, n) => {
|
|
123
123
|
const a = e.transaction(T, "readonly").objectStore(T).get(t);
|
|
124
|
-
a.onsuccess = () =>
|
|
124
|
+
a.onsuccess = () => r(a.result || null), a.onerror = () => n(a.error);
|
|
125
125
|
});
|
|
126
126
|
}
|
|
127
127
|
async getChunksByIds(t) {
|
|
128
128
|
if (t.length === 0) return [];
|
|
129
129
|
const e = await this.open();
|
|
130
|
-
return new Promise((
|
|
130
|
+
return new Promise((r, n) => {
|
|
131
131
|
const a = e.transaction(T, "readonly").objectStore(T), s = [];
|
|
132
132
|
let o = t.length;
|
|
133
133
|
for (const c of t) {
|
|
134
134
|
const h = a.get(c);
|
|
135
135
|
h.onsuccess = () => {
|
|
136
|
-
h.result && s.push(h.result), o--, o === 0 &&
|
|
137
|
-
}, h.onerror = () =>
|
|
136
|
+
h.result && s.push(h.result), o--, o === 0 && r(s);
|
|
137
|
+
}, h.onerror = () => n(h.error);
|
|
138
138
|
}
|
|
139
139
|
});
|
|
140
140
|
}
|
|
141
141
|
async getChunksBySession(t) {
|
|
142
142
|
const e = await this.open();
|
|
143
|
-
return new Promise((
|
|
143
|
+
return new Promise((r, n) => {
|
|
144
144
|
const s = e.transaction(T, "readonly").objectStore(T).index("sessionId").getAll(t);
|
|
145
145
|
s.onsuccess = () => {
|
|
146
146
|
const o = s.result || [];
|
|
147
|
-
o.sort((c, h) => c.startedAt !== h.startedAt ? c.startedAt - h.startedAt : c.sequence - h.sequence),
|
|
148
|
-
}, s.onerror = () =>
|
|
147
|
+
o.sort((c, h) => c.startedAt !== h.startedAt ? c.startedAt - h.startedAt : c.sequence - h.sequence), r(o);
|
|
148
|
+
}, s.onerror = () => n(s.error);
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
async getAllChunks() {
|
|
152
152
|
const t = await this.open();
|
|
153
|
-
return new Promise((e,
|
|
153
|
+
return new Promise((e, r) => {
|
|
154
154
|
const i = t.transaction(T, "readonly").objectStore(T).getAll();
|
|
155
|
-
i.onsuccess = () => e(i.result || []), i.onerror = () =>
|
|
155
|
+
i.onsuccess = () => e(i.result || []), i.onerror = () => r(i.error);
|
|
156
156
|
});
|
|
157
157
|
}
|
|
158
158
|
async deleteChunks(t) {
|
|
159
159
|
if (t.length === 0) return;
|
|
160
160
|
const e = await this.open();
|
|
161
|
-
return new Promise((
|
|
161
|
+
return new Promise((r, n) => {
|
|
162
162
|
const i = e.transaction(T, "readwrite"), a = i.objectStore(T);
|
|
163
163
|
for (const s of t)
|
|
164
164
|
a.delete(s);
|
|
165
|
-
i.oncomplete = () =>
|
|
165
|
+
i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
168
|
// --- INCIDENTS ---
|
|
169
169
|
async putIncident(t) {
|
|
170
170
|
const e = await this.open();
|
|
171
|
-
return new Promise((
|
|
171
|
+
return new Promise((r, n) => {
|
|
172
172
|
const i = e.transaction(R, "readwrite");
|
|
173
|
-
i.objectStore(R).put(t), i.oncomplete = () =>
|
|
173
|
+
i.objectStore(R).put(t), i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
174
174
|
});
|
|
175
175
|
}
|
|
176
176
|
async getIncident(t) {
|
|
177
177
|
const e = await this.open();
|
|
178
|
-
return new Promise((
|
|
178
|
+
return new Promise((r, n) => {
|
|
179
179
|
const a = e.transaction(R, "readonly").objectStore(R).get(t);
|
|
180
|
-
a.onsuccess = () =>
|
|
180
|
+
a.onsuccess = () => r(a.result || null), a.onerror = () => n(a.error);
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
183
|
async getPendingIncidentForSession(t) {
|
|
184
184
|
const e = await this.open();
|
|
185
|
-
return new Promise((
|
|
185
|
+
return new Promise((r, n) => {
|
|
186
186
|
const s = e.transaction(R, "readonly").objectStore(R).index("sessionId").getAll(t);
|
|
187
187
|
s.onsuccess = () => {
|
|
188
188
|
const c = (s.result || []).find((h) => h.state === "pending");
|
|
189
|
-
|
|
190
|
-
}, s.onerror = () =>
|
|
189
|
+
r(c || null);
|
|
190
|
+
}, s.onerror = () => n(s.error);
|
|
191
191
|
});
|
|
192
192
|
}
|
|
193
193
|
async listIncidents() {
|
|
194
194
|
const t = await this.open();
|
|
195
|
-
return new Promise((e,
|
|
195
|
+
return new Promise((e, r) => {
|
|
196
196
|
const i = t.transaction(R, "readonly").objectStore(R).getAll();
|
|
197
197
|
i.onsuccess = () => {
|
|
198
198
|
const s = (i.result || []).map((o) => ({
|
|
199
199
|
id: o.id,
|
|
200
200
|
reason: o.reason,
|
|
201
|
+
trigger: o.triggers[0],
|
|
201
202
|
startedAt: o.startedAt,
|
|
202
203
|
triggeredAt: o.triggeredAt,
|
|
203
204
|
finalizedAt: o.finalizedAt,
|
|
@@ -205,32 +206,32 @@ class Bt {
|
|
|
205
206
|
triggerCount: o.triggers.length
|
|
206
207
|
}));
|
|
207
208
|
s.sort((o, c) => c.triggeredAt - o.triggeredAt), e(s);
|
|
208
|
-
}, i.onerror = () =>
|
|
209
|
+
}, i.onerror = () => r(i.error);
|
|
209
210
|
});
|
|
210
211
|
}
|
|
211
212
|
async deleteIncident(t) {
|
|
212
213
|
const e = await this.open();
|
|
213
|
-
return new Promise((
|
|
214
|
+
return new Promise((r, n) => {
|
|
214
215
|
const i = e.transaction(R, "readwrite");
|
|
215
|
-
i.objectStore(R).delete(t), i.oncomplete = () =>
|
|
216
|
+
i.objectStore(R).delete(t), i.oncomplete = () => r(), i.onerror = () => n(i.error);
|
|
216
217
|
});
|
|
217
218
|
}
|
|
218
219
|
async getAllIncidents() {
|
|
219
220
|
const t = await this.open();
|
|
220
|
-
return new Promise((e,
|
|
221
|
+
return new Promise((e, r) => {
|
|
221
222
|
const i = t.transaction(R, "readonly").objectStore(R).getAll();
|
|
222
|
-
i.onsuccess = () => e(i.result || []), i.onerror = () =>
|
|
223
|
+
i.onsuccess = () => e(i.result || []), i.onerror = () => r(i.error);
|
|
223
224
|
});
|
|
224
225
|
}
|
|
225
226
|
// --- STATS & PURGE ---
|
|
226
227
|
async estimateStorageBytes() {
|
|
227
|
-
return (await this.getAllChunks()).reduce((e,
|
|
228
|
+
return (await this.getAllChunks()).reduce((e, r) => e + (r.sizeBytes || 0), 0);
|
|
228
229
|
}
|
|
229
230
|
async clearAll() {
|
|
230
231
|
const t = await this.open();
|
|
231
|
-
return new Promise((e,
|
|
232
|
-
const
|
|
233
|
-
|
|
232
|
+
return new Promise((e, r) => {
|
|
233
|
+
const n = t.transaction([O, T, R], "readwrite");
|
|
234
|
+
n.objectStore(O).clear(), n.objectStore(T).clear(), n.objectStore(R).clear(), n.oncomplete = () => e(), n.onerror = () => r(n.error);
|
|
234
235
|
});
|
|
235
236
|
}
|
|
236
237
|
}
|
|
@@ -239,13 +240,13 @@ function H(d, t) {
|
|
|
239
240
|
if (d > t) throw new Error("O conteúdo excede o limite máximo permitido de " + Math.round(t / 1024 / 1024) + " MiB.");
|
|
240
241
|
}
|
|
241
242
|
async function mt(d, t = X) {
|
|
242
|
-
const e = d.getReader(),
|
|
243
|
-
let
|
|
243
|
+
const e = d.getReader(), r = [];
|
|
244
|
+
let n = 0;
|
|
244
245
|
try {
|
|
245
246
|
for (; ; ) {
|
|
246
247
|
const { done: s, value: o } = await e.read();
|
|
247
248
|
if (s) break;
|
|
248
|
-
|
|
249
|
+
n += o.byteLength, H(n, t), r.push(o);
|
|
249
250
|
}
|
|
250
251
|
} catch (s) {
|
|
251
252
|
throw await e.cancel().catch(() => {
|
|
@@ -253,16 +254,16 @@ async function mt(d, t = X) {
|
|
|
253
254
|
} finally {
|
|
254
255
|
e.releaseLock();
|
|
255
256
|
}
|
|
256
|
-
const i = new Uint8Array(
|
|
257
|
+
const i = new Uint8Array(n);
|
|
257
258
|
let a = 0;
|
|
258
|
-
for (const s of
|
|
259
|
+
for (const s of r)
|
|
259
260
|
i.set(s, a), a += s.byteLength;
|
|
260
261
|
return i;
|
|
261
262
|
}
|
|
262
263
|
async function de(d, t = X) {
|
|
263
|
-
var
|
|
264
|
+
var r, n, i;
|
|
264
265
|
if (!d.ok) throw new Error("Falha ao baixar conteúdo (" + d.status + ").");
|
|
265
|
-
const e = Number((
|
|
266
|
+
const e = Number((n = (r = d.headers) == null ? void 0 : r.get) == null ? void 0 : n.call(r, "content-length"));
|
|
266
267
|
if (Number.isFinite(e) && e > t && (await ((i = d.body) == null ? void 0 : i.cancel().catch(() => {
|
|
267
268
|
})), H(e, t)), d.body)
|
|
268
269
|
return mt(d.body, t);
|
|
@@ -286,7 +287,7 @@ function Rt(d) {
|
|
|
286
287
|
async function kt(d) {
|
|
287
288
|
const t = typeof d == "string" ? new TextEncoder().encode(d) : d;
|
|
288
289
|
if (typeof CompressionStream < "u") {
|
|
289
|
-
const
|
|
290
|
+
const r = new Blob([t]).stream().pipeThrough(new CompressionStream("gzip")), i = await new Response(r).blob();
|
|
290
291
|
return new Uint8Array(await i.arrayBuffer());
|
|
291
292
|
}
|
|
292
293
|
return t;
|
|
@@ -295,8 +296,8 @@ async function Y(d, t = X) {
|
|
|
295
296
|
if (H(d.byteLength, t), !Rt(d))
|
|
296
297
|
return new TextDecoder().decode(d);
|
|
297
298
|
if (typeof DecompressionStream < "u") {
|
|
298
|
-
const
|
|
299
|
-
return new TextDecoder().decode(await mt(
|
|
299
|
+
const r = new Blob([d]).stream().pipeThrough(new DecompressionStream("gzip"));
|
|
300
|
+
return new TextDecoder().decode(await mt(r, t));
|
|
300
301
|
}
|
|
301
302
|
throw new Error("Este navegador não suporta descompressão Gzip. Use um arquivo JSON ou um navegador compatível.");
|
|
302
303
|
}
|
|
@@ -307,19 +308,19 @@ async function Dt(d) {
|
|
|
307
308
|
async function le(d, t = X) {
|
|
308
309
|
let e;
|
|
309
310
|
if (typeof d == "object" && d !== null && !(d instanceof ArrayBuffer) && !(d instanceof Uint8Array)) {
|
|
310
|
-
const
|
|
311
|
-
H(
|
|
311
|
+
const n = JSON.stringify(d);
|
|
312
|
+
H(n.length, t), H(new TextEncoder().encode(n).byteLength, t), e = d;
|
|
312
313
|
} else if (typeof d == "string") {
|
|
313
314
|
H(d.length, t), H(new TextEncoder().encode(d).byteLength, t);
|
|
314
315
|
try {
|
|
315
316
|
e = JSON.parse(d);
|
|
316
|
-
} catch (
|
|
317
|
+
} catch (n) {
|
|
317
318
|
throw new Error(
|
|
318
|
-
`Falha ao converter dados em JSON: ${
|
|
319
|
+
`Falha ao converter dados em JSON: ${n instanceof Error ? n.message : String(n)}`
|
|
319
320
|
);
|
|
320
321
|
}
|
|
321
322
|
} else if (d instanceof ArrayBuffer || d instanceof Uint8Array) {
|
|
322
|
-
const
|
|
323
|
+
const n = d instanceof Uint8Array ? d : new Uint8Array(d), i = await Y(n, t);
|
|
323
324
|
try {
|
|
324
325
|
e = JSON.parse(i);
|
|
325
326
|
} catch (a) {
|
|
@@ -329,13 +330,13 @@ async function le(d, t = X) {
|
|
|
329
330
|
}
|
|
330
331
|
} else
|
|
331
332
|
throw new Error("Formato de dados inválido para o artefato.");
|
|
332
|
-
const
|
|
333
|
-
if (!
|
|
334
|
-
throw new Error(`Artefato inválido: ${
|
|
335
|
-
return
|
|
333
|
+
const r = It(e);
|
|
334
|
+
if (!r.success)
|
|
335
|
+
throw new Error(`Artefato inválido: ${r.errors.join(", ")}`);
|
|
336
|
+
return r.data;
|
|
336
337
|
}
|
|
337
338
|
class Lt {
|
|
338
|
-
constructor(t, e,
|
|
339
|
+
constructor(t, e, r, n, i) {
|
|
339
340
|
l(this, "db");
|
|
340
341
|
l(this, "config");
|
|
341
342
|
l(this, "sessionId");
|
|
@@ -352,13 +353,13 @@ class Lt {
|
|
|
352
353
|
l(this, "visibilityChangeHandler");
|
|
353
354
|
l(this, "flushCount", 0);
|
|
354
355
|
l(this, "onFlushMetricsCallback");
|
|
355
|
-
this.db = t, this.sessionId = e, this.tabId =
|
|
356
|
-
flushIntervalMs: (
|
|
357
|
-
maxBatchEvents: (
|
|
358
|
-
chunkDurationMs: (
|
|
359
|
-
initialChunkSequence: (
|
|
360
|
-
onFlushMetrics:
|
|
361
|
-
}, this.chunkSequence = (
|
|
356
|
+
this.db = t, this.sessionId = e, this.tabId = r, this.config = {
|
|
357
|
+
flushIntervalMs: (n == null ? void 0 : n.flushIntervalMs) ?? 1e3,
|
|
358
|
+
maxBatchEvents: (n == null ? void 0 : n.maxBatchEvents) ?? 250,
|
|
359
|
+
chunkDurationMs: (n == null ? void 0 : n.chunkDurationMs) ?? 6e4,
|
|
360
|
+
initialChunkSequence: (n == null ? void 0 : n.initialChunkSequence) ?? 0,
|
|
361
|
+
onFlushMetrics: n == null ? void 0 : n.onFlushMetrics
|
|
362
|
+
}, this.chunkSequence = (n == null ? void 0 : n.initialChunkSequence) ?? 0, this.onErrorCallback = i, this.onFlushMetricsCallback = n == null ? void 0 : n.onFlushMetrics, this.initLifecycleListeners();
|
|
362
363
|
}
|
|
363
364
|
getChunkSequence() {
|
|
364
365
|
return this.chunkSequence;
|
|
@@ -391,10 +392,10 @@ class Lt {
|
|
|
391
392
|
return this.writeChain;
|
|
392
393
|
const t = [...this.pendingTimelineEvents], e = [...this.pendingReplayEvents];
|
|
393
394
|
this.pendingTimelineEvents = [], this.pendingReplayEvents = [];
|
|
394
|
-
const
|
|
395
|
+
const r = Date.now(), n = [
|
|
395
396
|
...t.map((f) => f.timestamp),
|
|
396
397
|
...e.map((f) => f.timestamp)
|
|
397
|
-
], i =
|
|
398
|
+
], i = n.length > 0 ? Math.min(...n) : r, a = n.length > 0 ? Math.max(...n) : r;
|
|
398
399
|
this.chunkSequence++;
|
|
399
400
|
const s = e.filter((f) => f.type === 2).map((f) => f.timestamp), o = {
|
|
400
401
|
id: `chk_${this.sessionId}_${this.chunkSequence}_${i}`,
|
|
@@ -408,7 +409,7 @@ class Lt {
|
|
|
408
409
|
snapshotTimestamps: s,
|
|
409
410
|
timeline: t,
|
|
410
411
|
replay: e
|
|
411
|
-
}, c = ++this.flushCount, h = e.length, u = t.length, p = h,
|
|
412
|
+
}, c = ++this.flushCount, h = e.length, u = t.length, p = h, g = u, b = p + g;
|
|
412
413
|
return this.pendingWritesCount++, this.writeChain = this.writeChain.then(async () => {
|
|
413
414
|
const f = performance.now();
|
|
414
415
|
let m = 0, k = 0;
|
|
@@ -442,8 +443,8 @@ class Lt {
|
|
|
442
443
|
replayEventsInBatch: h,
|
|
443
444
|
timelineEventsInBatch: u,
|
|
444
445
|
totalReplayInChunk: p,
|
|
445
|
-
totalTimelineInChunk:
|
|
446
|
-
totalEventsInChunk:
|
|
446
|
+
totalTimelineInChunk: g,
|
|
447
|
+
totalEventsInChunk: b,
|
|
447
448
|
timestamp: Date.now()
|
|
448
449
|
}), this.onChunkPersistedCallback && this.onChunkPersistedCallback(o);
|
|
449
450
|
}).catch((f) => {
|
|
@@ -479,26 +480,26 @@ class Pt {
|
|
|
479
480
|
* 3. Se exceder maxStorageMb, exclui os chunks não protegidos mais antigos.
|
|
480
481
|
*/
|
|
481
482
|
async prune(t = Date.now()) {
|
|
482
|
-
const e = await this.db.getAllIncidents(),
|
|
483
|
-
for (const
|
|
484
|
-
for (const
|
|
485
|
-
|
|
486
|
-
const
|
|
487
|
-
for (const
|
|
488
|
-
!
|
|
483
|
+
const e = await this.db.getAllIncidents(), r = /* @__PURE__ */ new Set();
|
|
484
|
+
for (const g of e)
|
|
485
|
+
for (const b of g.chunkIds)
|
|
486
|
+
r.add(b);
|
|
487
|
+
const n = await this.db.getAllChunks(), i = this.config.bufferMinutes * 60 * 1e3, a = t - i, s = [], o = [];
|
|
488
|
+
for (const g of n)
|
|
489
|
+
!r.has(g.id) && g.endedAt < a ? s.push(g) : o.push(g);
|
|
489
490
|
const c = this.config.maxStorageMb * 1024 * 1024;
|
|
490
|
-
let h = o.reduce((
|
|
491
|
+
let h = o.reduce((g, b) => g + (b.sizeBytes || 0), 0);
|
|
491
492
|
if (h > c) {
|
|
492
|
-
const
|
|
493
|
-
for (const
|
|
493
|
+
const g = o.filter((b) => !r.has(b.id)).sort((b, f) => b.startedAt - f.startedAt);
|
|
494
|
+
for (const b of g) {
|
|
494
495
|
if (h <= c) break;
|
|
495
|
-
s.push(
|
|
496
|
+
s.push(b), h -= b.sizeBytes || 0;
|
|
496
497
|
}
|
|
497
498
|
}
|
|
498
|
-
const u = s.map((
|
|
499
|
+
const u = s.map((g) => g.id);
|
|
499
500
|
let p = 0;
|
|
500
|
-
for (const
|
|
501
|
-
p +=
|
|
501
|
+
for (const g of s)
|
|
502
|
+
p += g.sizeBytes || 0;
|
|
502
503
|
return u.length > 0 && await this.db.deleteChunks(u), {
|
|
503
504
|
deletedChunkIds: u,
|
|
504
505
|
reclaimedBytes: p,
|
|
@@ -514,12 +515,12 @@ class Pt {
|
|
|
514
515
|
for (const c of t)
|
|
515
516
|
for (const h of c.chunkIds)
|
|
516
517
|
e.add(h);
|
|
517
|
-
const
|
|
518
|
-
for (const c of n)
|
|
519
|
-
e.has(c.id) ? i.push(c) : r.push(c);
|
|
520
|
-
const a = r.map((c) => c.id);
|
|
521
|
-
let s = 0;
|
|
518
|
+
const r = await this.db.getAllChunks(), n = [], i = [];
|
|
522
519
|
for (const c of r)
|
|
520
|
+
e.has(c.id) ? i.push(c) : n.push(c);
|
|
521
|
+
const a = n.map((c) => c.id);
|
|
522
|
+
let s = 0;
|
|
523
|
+
for (const c of n)
|
|
523
524
|
s += c.sizeBytes || 0;
|
|
524
525
|
a.length > 0 && await this.db.deleteChunks(a);
|
|
525
526
|
const o = i.reduce((c, h) => c + (h.sizeBytes || 0), 0);
|
|
@@ -537,30 +538,30 @@ class Pt {
|
|
|
537
538
|
for (const o of t)
|
|
538
539
|
for (const c of o.chunkIds)
|
|
539
540
|
e.add(c);
|
|
540
|
-
const
|
|
541
|
-
let
|
|
542
|
-
for (const o of
|
|
541
|
+
const r = await this.db.getAllChunks();
|
|
542
|
+
let n = 0, i = 0;
|
|
543
|
+
for (const o of r) {
|
|
543
544
|
const c = o.sizeBytes || 0;
|
|
544
|
-
e.has(o.id) ?
|
|
545
|
+
e.has(o.id) ? n += c : i += c;
|
|
545
546
|
}
|
|
546
|
-
const a =
|
|
547
|
+
const a = n + i, s = this.config.maxStorageMb * 1024 * 1024;
|
|
547
548
|
return {
|
|
548
549
|
totalBytes: a,
|
|
549
|
-
protectedBytes:
|
|
550
|
+
protectedBytes: n,
|
|
550
551
|
bufferBytes: i,
|
|
551
552
|
maxStorageBytes: s,
|
|
552
553
|
isOverLimit: a > s,
|
|
553
|
-
protectedExceedsLimit:
|
|
554
|
+
protectedExceedsLimit: n > s,
|
|
554
555
|
incidentCount: t.length
|
|
555
556
|
};
|
|
556
557
|
}
|
|
557
558
|
}
|
|
558
559
|
function lt(d, t, e) {
|
|
559
|
-
const
|
|
560
|
-
return `${d}_${t}_${e}_${
|
|
560
|
+
const r = typeof crypto < "u" && typeof crypto.randomUUID == "function" ? crypto.randomUUID() : Math.random().toString(36).substring(2, 10);
|
|
561
|
+
return `${d}_${t}_${e}_${r}`;
|
|
561
562
|
}
|
|
562
563
|
function yt(d, t, e) {
|
|
563
|
-
const
|
|
564
|
+
const r = [];
|
|
564
565
|
if (!d || d.length === 0)
|
|
565
566
|
return {
|
|
566
567
|
events: [],
|
|
@@ -569,74 +570,74 @@ function yt(d, t, e) {
|
|
|
569
570
|
requestedEndedAt: e,
|
|
570
571
|
preparationEventCount: 0
|
|
571
572
|
},
|
|
572
|
-
degradedReasons:
|
|
573
|
+
degradedReasons: r
|
|
573
574
|
};
|
|
574
|
-
const
|
|
575
|
-
(
|
|
576
|
-
), a =
|
|
575
|
+
const n = [...d].sort((b, f) => b.timestamp - f.timestamp), i = n.filter(
|
|
576
|
+
(b) => b.timestamp >= t && b.timestamp <= e
|
|
577
|
+
), a = n.filter((b) => b.type === 2 && b.timestamp <= t), s = a.length > 0 ? a[a.length - 1] : null;
|
|
577
578
|
if (!s) {
|
|
578
|
-
|
|
579
|
-
let
|
|
579
|
+
r.push("Não há snapshot para reconstruir o início da gravação.");
|
|
580
|
+
let b = 0;
|
|
580
581
|
if (!i.some((m) => m.type === 4)) {
|
|
581
|
-
const m =
|
|
582
|
+
const m = n.filter((I) => I.type === 4 && I.timestamp <= t), k = m.length > 0 ? m[m.length - 1] : null;
|
|
582
583
|
if (k)
|
|
583
|
-
return
|
|
584
|
+
return b = 1, {
|
|
584
585
|
events: [{ ...k, timestamp: t - 1 }, ...i],
|
|
585
586
|
replayWindow: {
|
|
586
587
|
requestedStartedAt: t,
|
|
587
588
|
requestedEndedAt: e,
|
|
588
|
-
preparationEventCount:
|
|
589
|
+
preparationEventCount: b
|
|
589
590
|
},
|
|
590
|
-
degradedReasons:
|
|
591
|
+
degradedReasons: r
|
|
591
592
|
};
|
|
592
|
-
|
|
593
|
+
r.push("Não há evento de metadados (Meta) anterior ao início da gravação.");
|
|
593
594
|
}
|
|
594
595
|
return {
|
|
595
596
|
events: i,
|
|
596
597
|
replayWindow: {
|
|
597
598
|
requestedStartedAt: t,
|
|
598
599
|
requestedEndedAt: e,
|
|
599
|
-
preparationEventCount:
|
|
600
|
+
preparationEventCount: b
|
|
600
601
|
},
|
|
601
|
-
degradedReasons:
|
|
602
|
+
degradedReasons: r
|
|
602
603
|
};
|
|
603
604
|
}
|
|
604
|
-
const o =
|
|
605
|
-
(
|
|
606
|
-
), h = c.length > 0 ? c[c.length - 1] : null, u =
|
|
607
|
-
(
|
|
605
|
+
const o = n.lastIndexOf(s), c = n.filter(
|
|
606
|
+
(b, f) => b.type === 4 && f <= o && b.timestamp <= t
|
|
607
|
+
), h = c.length > 0 ? c[c.length - 1] : null, u = n.slice(o + 1).filter(
|
|
608
|
+
(b) => b.timestamp < t && b.type !== 2 && b.type !== 4
|
|
608
609
|
), p = [];
|
|
609
|
-
let
|
|
610
|
+
let g = 0;
|
|
610
611
|
h && (p.push({
|
|
611
612
|
...h,
|
|
612
613
|
timestamp: t - 1
|
|
613
|
-
}),
|
|
614
|
+
}), g++), p.push({
|
|
614
615
|
...s,
|
|
615
616
|
timestamp: t
|
|
616
|
-
}),
|
|
617
|
-
for (const
|
|
617
|
+
}), g++;
|
|
618
|
+
for (const b of u)
|
|
618
619
|
p.push({
|
|
619
|
-
...
|
|
620
|
+
...b,
|
|
620
621
|
timestamp: t
|
|
621
|
-
}),
|
|
622
|
-
for (const
|
|
623
|
-
|
|
622
|
+
}), g++;
|
|
623
|
+
for (const b of i)
|
|
624
|
+
b.type === 2 && b.timestamp === s.timestamp || h && b.type === 4 && b.timestamp === h.timestamp || p.push(b);
|
|
624
625
|
return {
|
|
625
626
|
events: p,
|
|
626
627
|
replayWindow: {
|
|
627
628
|
requestedStartedAt: t,
|
|
628
629
|
requestedEndedAt: e,
|
|
629
|
-
preparationEventCount:
|
|
630
|
+
preparationEventCount: g,
|
|
630
631
|
baseSnapshotOriginalTimestamp: s.timestamp
|
|
631
632
|
},
|
|
632
|
-
degradedReasons:
|
|
633
|
+
degradedReasons: r
|
|
633
634
|
};
|
|
634
635
|
}
|
|
635
636
|
function he(d, t, e) {
|
|
636
637
|
return yt(d, t, e).events;
|
|
637
638
|
}
|
|
638
639
|
class ht {
|
|
639
|
-
constructor(t, e,
|
|
640
|
+
constructor(t, e, r, n, i) {
|
|
640
641
|
l(this, "db");
|
|
641
642
|
l(this, "sessionId");
|
|
642
643
|
l(this, "tabId");
|
|
@@ -654,14 +655,14 @@ class ht {
|
|
|
654
655
|
l(this, "recoveredBaseIncidentId");
|
|
655
656
|
l(this, "baseRecoveredDroppedEvents", 0);
|
|
656
657
|
l(this, "isDestroyed", !1);
|
|
657
|
-
this.db = t, this.sessionId = e, this.tabId =
|
|
658
|
+
this.db = t, this.sessionId = e, this.tabId = r, typeof n == "function" ? (this.environmentProvider = n, this.fallbackEnvironment = {
|
|
658
659
|
url: typeof window < "u" ? window.location.href : "http://localhost",
|
|
659
660
|
userAgent: typeof window < "u" ? window.navigator.userAgent : "node",
|
|
660
661
|
viewport: {
|
|
661
662
|
width: typeof window < "u" ? window.innerWidth : 1280,
|
|
662
663
|
height: typeof window < "u" ? window.innerHeight : 720
|
|
663
664
|
}
|
|
664
|
-
}) : (this.fallbackEnvironment =
|
|
665
|
+
}) : (this.fallbackEnvironment = n, this.environmentProvider = () => n), this.config = {
|
|
665
666
|
afterErrorSeconds: (i == null ? void 0 : i.afterErrorSeconds) ?? 15,
|
|
666
667
|
recorderVersion: (i == null ? void 0 : i.recorderVersion) ?? "0.1.0",
|
|
667
668
|
context: i == null ? void 0 : i.context,
|
|
@@ -678,19 +679,19 @@ class ht {
|
|
|
678
679
|
}
|
|
679
680
|
}
|
|
680
681
|
resolveFallbackEnvironment(t, e) {
|
|
681
|
-
const
|
|
682
|
+
const r = this.getEnvironment(), n = e.filter(
|
|
682
683
|
(a) => a.type === "navigation" && a.timestamp <= t.triggeredAt
|
|
683
|
-
), i =
|
|
684
|
+
), i = n.length > 0 ? n[n.length - 1] : null;
|
|
684
685
|
return {
|
|
685
|
-
...
|
|
686
|
-
url: i ? i.toUrl :
|
|
686
|
+
...r,
|
|
687
|
+
url: i ? i.toUrl : r.url
|
|
687
688
|
};
|
|
688
689
|
}
|
|
689
690
|
serializeOperation(t) {
|
|
690
691
|
if (this.isDestroyed)
|
|
691
692
|
return Promise.reject(new Error("IncidentManager foi destruído."));
|
|
692
693
|
let e;
|
|
693
|
-
const
|
|
694
|
+
const r = async () => {
|
|
694
695
|
try {
|
|
695
696
|
return await t();
|
|
696
697
|
} catch (i) {
|
|
@@ -705,16 +706,16 @@ class ht {
|
|
|
705
706
|
}
|
|
706
707
|
};
|
|
707
708
|
if (!this.activeOperation)
|
|
708
|
-
return e =
|
|
709
|
-
const
|
|
710
|
-
return e = this.activeOperation.then(
|
|
709
|
+
return e = r(), this.activeOperation = e, e;
|
|
710
|
+
const n = () => r();
|
|
711
|
+
return e = this.activeOperation.then(n, n), this.activeOperation = e, e;
|
|
711
712
|
}
|
|
712
713
|
runExclusive(t) {
|
|
713
714
|
return this.serializeOperation(t);
|
|
714
715
|
}
|
|
715
716
|
computeCurrentDroppedEvents(t) {
|
|
716
|
-
var
|
|
717
|
-
const e = ((
|
|
717
|
+
var r, n;
|
|
718
|
+
const e = ((n = (r = this.config).getDroppedEventsCount) == null ? void 0 : n.call(r)) ?? 0;
|
|
718
719
|
return this.recoveredBaseIncidentId === t.id ? this.baseRecoveredDroppedEvents + e : typeof this.config.getDroppedEventsCount == "function" ? e : t.droppedEvents ?? 0;
|
|
719
720
|
}
|
|
720
721
|
/**
|
|
@@ -735,11 +736,11 @@ class ht {
|
|
|
735
736
|
async protectSessionChunks() {
|
|
736
737
|
if (!this.pendingIncident) return;
|
|
737
738
|
const t = await this.db.getChunksBySession(this.sessionId), e = new Set(this.pendingIncident.chunkIds);
|
|
738
|
-
let
|
|
739
|
+
let r = !1;
|
|
739
740
|
for (const i of t)
|
|
740
|
-
e.has(i.id) || (this.pendingIncident.chunkIds.push(i.id), e.add(i.id),
|
|
741
|
-
const
|
|
742
|
-
this.pendingIncident.droppedEvents !==
|
|
741
|
+
e.has(i.id) || (this.pendingIncident.chunkIds.push(i.id), e.add(i.id), r = !0);
|
|
742
|
+
const n = this.computeCurrentDroppedEvents(this.pendingIncident);
|
|
743
|
+
this.pendingIncident.droppedEvents !== n && (this.pendingIncident.droppedEvents = n, r = !0), r && await this.db.putIncident(this.pendingIncident);
|
|
743
744
|
}
|
|
744
745
|
setOnError(t) {
|
|
745
746
|
this.onErrorCallback = t;
|
|
@@ -768,41 +769,41 @@ class ht {
|
|
|
768
769
|
if (e >= t.finalizeAt)
|
|
769
770
|
await this.executeFinalize(t.id);
|
|
770
771
|
else {
|
|
771
|
-
const
|
|
772
|
+
const r = t.finalizeAt - e;
|
|
772
773
|
this.finalizeTimer = setTimeout(() => {
|
|
773
774
|
this.finalize(t.id).catch(() => {
|
|
774
775
|
});
|
|
775
|
-
},
|
|
776
|
+
}, r);
|
|
776
777
|
}
|
|
777
778
|
}
|
|
778
779
|
/**
|
|
779
780
|
* Registra um gatilho de incidente (automático ou manual).
|
|
780
781
|
* As chamadas são serializadas para evitar race conditions entre múltiplos erros concorrentes.
|
|
781
782
|
*/
|
|
782
|
-
trigger(t, e,
|
|
783
|
+
trigger(t, e, r) {
|
|
783
784
|
return this.serializeOperation(
|
|
784
|
-
() => this.executeTrigger(t, e,
|
|
785
|
+
() => this.executeTrigger(t, e, r)
|
|
785
786
|
);
|
|
786
787
|
}
|
|
787
|
-
async executeTrigger(t, e,
|
|
788
|
+
async executeTrigger(t, e, r) {
|
|
788
789
|
var o, c, h, u;
|
|
789
|
-
const
|
|
790
|
+
const n = e.timestamp || Date.now();
|
|
790
791
|
if (t === "manual")
|
|
791
|
-
return this.createAndFinalizeManualIncident(e,
|
|
792
|
+
return this.createAndFinalizeManualIncident(e, n, r);
|
|
792
793
|
if (!this.pendingIncident) {
|
|
793
794
|
this.recoveredBaseIncidentId = void 0, this.baseRecoveredDroppedEvents = 0;
|
|
794
|
-
const p = lt("inc", this.sessionId,
|
|
795
|
+
const p = lt("inc", this.sessionId, n), g = await this.db.getChunksBySession(this.sessionId), b = g.length > 0 ? g[0].startedAt : n, f = ((c = (o = this.config).getDroppedEventsCount) == null ? void 0 : c.call(o)) ?? 0, m = {
|
|
795
796
|
id: p,
|
|
796
797
|
sessionId: this.sessionId,
|
|
797
798
|
tabId: this.tabId,
|
|
798
799
|
reason: t,
|
|
799
800
|
triggers: [e],
|
|
800
|
-
startedAt:
|
|
801
|
-
triggeredAt:
|
|
802
|
-
finalizeAt:
|
|
801
|
+
startedAt: b,
|
|
802
|
+
triggeredAt: n,
|
|
803
|
+
finalizeAt: n + this.config.afterErrorSeconds * 1e3,
|
|
803
804
|
state: "pending",
|
|
804
805
|
recordingIssues: ((u = (h = this.config).getRecordingIssues) == null ? void 0 : u.call(h)) ?? [],
|
|
805
|
-
chunkIds:
|
|
806
|
+
chunkIds: g.map((k) => k.id),
|
|
806
807
|
environment: this.getEnvironment(),
|
|
807
808
|
droppedEvents: f
|
|
808
809
|
};
|
|
@@ -812,10 +813,10 @@ class ht {
|
|
|
812
813
|
}, this.config.afterErrorSeconds * 1e3)), this.onIncidentPendingCallback && this.onIncidentPendingCallback(m), p;
|
|
813
814
|
}
|
|
814
815
|
const i = this.pendingIncident, a = i.triggers.some(
|
|
815
|
-
(p) => p.signature === e.signature &&
|
|
816
|
+
(p) => p.signature === e.signature && n - p.timestamp < 1e4
|
|
816
817
|
);
|
|
817
|
-
if (i.triggers.push(e), !a && !this.hasExtendedOnce && (this.hasExtendedOnce = !0, i.finalizeAt = Math.max(i.finalizeAt,
|
|
818
|
-
const p = i.finalizeAt -
|
|
818
|
+
if (i.triggers.push(e), !a && !this.hasExtendedOnce && (this.hasExtendedOnce = !0, i.finalizeAt = Math.max(i.finalizeAt, n + this.config.afterErrorSeconds * 1e3), this.finalizeTimer && clearTimeout(this.finalizeTimer), !this.isDestroyed)) {
|
|
819
|
+
const p = i.finalizeAt - n;
|
|
819
820
|
this.finalizeTimer = setTimeout(() => {
|
|
820
821
|
this.finalize(i.id).catch(() => {
|
|
821
822
|
});
|
|
@@ -832,25 +833,25 @@ class ht {
|
|
|
832
833
|
if (t.snapshotTimestamps && t.snapshotTimestamps.length > 0)
|
|
833
834
|
return t.snapshotTimestamps;
|
|
834
835
|
if (t.replay && t.replay.length > 0) {
|
|
835
|
-
const
|
|
836
|
-
if (
|
|
836
|
+
const r = t.replay.filter((n) => n.type === 2).map((n) => n.timestamp);
|
|
837
|
+
if (r.length > 0) return r;
|
|
837
838
|
}
|
|
838
839
|
if (t.replayCompressed && t.replayCompressed.length > 0)
|
|
839
840
|
try {
|
|
840
|
-
const
|
|
841
|
+
const r = await Y(t.replayCompressed), i = JSON.parse(r).filter((a) => a.type === 2).map((a) => a.timestamp);
|
|
841
842
|
if (i.length > 0) return i;
|
|
842
843
|
} catch {
|
|
843
844
|
}
|
|
844
845
|
return t.hasFullSnapshot && (e == null || e()), [];
|
|
845
846
|
}
|
|
846
|
-
async createAndFinalizeManualIncident(t, e,
|
|
847
|
-
var
|
|
848
|
-
const
|
|
847
|
+
async createAndFinalizeManualIncident(t, e, r) {
|
|
848
|
+
var g, b, f, m;
|
|
849
|
+
const n = lt("inc_manual", this.sessionId, e), i = await this.db.getChunksBySession(this.sessionId);
|
|
849
850
|
i.sort((k, I) => k.startedAt !== I.startedAt ? k.startedAt - I.startedAt : k.sequence - I.sequence);
|
|
850
851
|
const a = i.length > 0 ? i[0].startedAt : e;
|
|
851
852
|
let s = i, o = a, c = !1;
|
|
852
|
-
if (
|
|
853
|
-
const k =
|
|
853
|
+
if (r && r > 0) {
|
|
854
|
+
const k = r * 1e3, I = Math.max(a, e - k);
|
|
854
855
|
o = I;
|
|
855
856
|
const y = await Promise.all(
|
|
856
857
|
i.map(
|
|
@@ -885,10 +886,10 @@ class ht {
|
|
|
885
886
|
s = i.slice(C, E + 1);
|
|
886
887
|
}
|
|
887
888
|
}
|
|
888
|
-
const h = [...((
|
|
889
|
+
const h = [...((b = (g = this.config).getRecordingIssues) == null ? void 0 : b.call(g)) ?? []];
|
|
889
890
|
c && h.push("Ausência de prova temporal para snapshot em lote legado com hasFullSnapshot.");
|
|
890
891
|
const u = ((m = (f = this.config).getDroppedEventsCount) == null ? void 0 : m.call(f)) ?? 0, p = {
|
|
891
|
-
id:
|
|
892
|
+
id: n,
|
|
892
893
|
sessionId: this.sessionId,
|
|
893
894
|
tabId: this.tabId,
|
|
894
895
|
reason: "manual",
|
|
@@ -903,11 +904,11 @@ class ht {
|
|
|
903
904
|
environment: this.getEnvironment(),
|
|
904
905
|
droppedEvents: u
|
|
905
906
|
};
|
|
906
|
-
return await this.db.putIncident(p), this.onIncidentFinalizedCallback && this.onIncidentFinalizedCallback(p),
|
|
907
|
+
return await this.db.putIncident(p), this.onIncidentFinalizedCallback && this.onIncidentFinalizedCallback(p), n;
|
|
907
908
|
}
|
|
908
909
|
async executeManualTrigger(t, e) {
|
|
909
|
-
const
|
|
910
|
-
return this.createAndFinalizeManualIncident(t,
|
|
910
|
+
const r = t.timestamp || Date.now();
|
|
911
|
+
return this.createAndFinalizeManualIncident(t, r, e);
|
|
911
912
|
}
|
|
912
913
|
/**
|
|
913
914
|
* Finaliza um incidente pendente.
|
|
@@ -930,14 +931,14 @@ class ht {
|
|
|
930
931
|
((o = this.pendingIncident) == null ? void 0 : o.id) === t && (this.pendingIncident = null, this.hasExtendedOnce = !1);
|
|
931
932
|
return;
|
|
932
933
|
}
|
|
933
|
-
const
|
|
934
|
-
e.recordingIssues = [.../* @__PURE__ */ new Set([...e.recordingIssues ?? [], ...((h = (c = this.config).getRecordingIssues) == null ? void 0 : h.call(c)) ?? []])], e.state = "finalized", e.finalizedAt =
|
|
934
|
+
const r = Date.now(), n = e.finalizeAt ? Math.min(r, e.finalizeAt) : r, a = (await this.db.getChunksBySession(this.sessionId)).filter((p) => p.startedAt <= n), s = Array.from(/* @__PURE__ */ new Set([...e.chunkIds, ...a.map((p) => p.id)]));
|
|
935
|
+
e.recordingIssues = [.../* @__PURE__ */ new Set([...e.recordingIssues ?? [], ...((h = (c = this.config).getRecordingIssues) == null ? void 0 : h.call(c)) ?? []])], e.state = "finalized", e.finalizedAt = n, e.chunkIds = s, e.droppedEvents = this.computeCurrentDroppedEvents(e), await this.db.putIncident(e), ((u = this.pendingIncident) == null ? void 0 : u.id) === t && (this.pendingIncident = null, this.recoveredBaseIncidentId = void 0, this.baseRecoveredDroppedEvents = 0, this.hasExtendedOnce = !1), this.onIncidentFinalizedCallback && this.onIncidentFinalizedCallback(e);
|
|
935
936
|
}
|
|
936
937
|
/**
|
|
937
938
|
* Exporta um incidente em um artefato canônico v1 (.ffr.json).
|
|
938
939
|
*/
|
|
939
940
|
async exportArtifact(t) {
|
|
940
|
-
var
|
|
941
|
+
var j, et, rt, nt, it, at, st, ot, ct;
|
|
941
942
|
if (this.beforeFinalizeCallback)
|
|
942
943
|
try {
|
|
943
944
|
await this.beforeFinalizeCallback();
|
|
@@ -946,38 +947,38 @@ class ht {
|
|
|
946
947
|
const e = await this.db.getIncident(t);
|
|
947
948
|
if (!e)
|
|
948
949
|
throw new Error(`Incidente "${t}" não encontrado.`);
|
|
949
|
-
const
|
|
950
|
+
const r = new Set(e.recordingIssues ?? []), n = await this.db.getChunksByIds(e.chunkIds), i = new Set(n.map((x) => x.id));
|
|
950
951
|
let a = !1, s = !1;
|
|
951
|
-
e.chunkIds.filter((x) => !i.has(x)).length > 0 && (a = !0,
|
|
952
|
-
const c =
|
|
952
|
+
e.chunkIds.filter((x) => !i.has(x)).length > 0 && (a = !0, r.add("Um ou mais lotes da gravação não foram encontrados.")), n.sort((x, P) => x.startedAt !== P.startedAt ? x.startedAt - P.startedAt : x.sequence - P.sequence);
|
|
953
|
+
const c = n.flatMap((x) => x.timeline || []), u = Et(c).filter(
|
|
953
954
|
(x) => x.timestamp >= e.startedAt && x.timestamp <= (e.finalizedAt ?? e.finalizeAt)
|
|
954
955
|
), p = (await Promise.all(
|
|
955
|
-
|
|
956
|
+
n.map(async (x) => {
|
|
956
957
|
if (x.replayCompressed && x.replayCompressed.length > 0)
|
|
957
958
|
try {
|
|
958
959
|
const P = await Y(x.replayCompressed), dt = JSON.parse(P);
|
|
959
960
|
if (!Array.isArray(dt)) throw new Error("Replay inválido");
|
|
960
961
|
return dt;
|
|
961
962
|
} catch {
|
|
962
|
-
return s = !0,
|
|
963
|
+
return s = !0, r.add("Parte do replay não pôde ser descomprimida; a gravação pode estar incompleta."), x.replay || [];
|
|
963
964
|
}
|
|
964
965
|
return x.replay || [];
|
|
965
966
|
})
|
|
966
|
-
)).flat(), { events:
|
|
967
|
+
)).flat(), { events: g, replayWindow: b, degradedReasons: f } = yt(
|
|
967
968
|
p,
|
|
968
969
|
e.startedAt,
|
|
969
970
|
e.finalizedAt ?? e.finalizeAt
|
|
970
971
|
);
|
|
971
972
|
for (const x of f)
|
|
972
|
-
|
|
973
|
-
const m =
|
|
973
|
+
r.add(x);
|
|
974
|
+
const m = n.reduce((x, P) => x + (P.sizeBytes || 0), 0), k = e.droppedEvents ?? ((et = (j = this.config).getDroppedEventsCount) == null ? void 0 : et.call(j)) ?? 0, I = a || s;
|
|
974
975
|
let y;
|
|
975
976
|
if (this.config.getContext)
|
|
976
977
|
try {
|
|
977
978
|
y = await this.config.getContext();
|
|
978
979
|
} catch {
|
|
979
980
|
}
|
|
980
|
-
const w = this.config.context, E = (y == null ? void 0 : y.release) ?? (w == null ? void 0 : w.release) ?? ((
|
|
981
|
+
const w = this.config.context, E = (y == null ? void 0 : y.release) ?? (w == null ? void 0 : w.release) ?? ((rt = e.environment) == null ? void 0 : rt.appVersion) ?? this.getEnvironment().appVersion, S = (y == null ? void 0 : y.environment) ?? (w == null ? void 0 : w.environment), C = (y == null ? void 0 : y.traceId) ?? (w == null ? void 0 : w.traceId), M = (y == null ? void 0 : y.spanId) ?? (w == null ? void 0 : w.spanId), A = typeof C == "string" && /^[0-9a-f]{32}$/i.test(C) ? C.toLowerCase() : void 0, _ = A && typeof M == "string" && /^[0-9a-f]{16}$/i.test(M) ? M.toLowerCase() : void 0, B = A ? {
|
|
981
982
|
traceId: A,
|
|
982
983
|
..._ ? { spanId: _ } : {}
|
|
983
984
|
} : void 0;
|
|
@@ -998,7 +999,7 @@ class ht {
|
|
|
998
999
|
startedAt: e.startedAt,
|
|
999
1000
|
triggeredAt: e.triggeredAt,
|
|
1000
1001
|
finalizedAt: e.finalizedAt ?? e.finalizeAt,
|
|
1001
|
-
annotationImage: ((at = (it = (
|
|
1002
|
+
annotationImage: ((at = (it = (nt = e.triggers) == null ? void 0 : nt.find((x) => {
|
|
1002
1003
|
var P;
|
|
1003
1004
|
return (P = x.detail) == null ? void 0 : P.annotationImage;
|
|
1004
1005
|
})) == null ? void 0 : it.detail) == null ? void 0 : at.annotationImage) || void 0,
|
|
@@ -1008,15 +1009,15 @@ class ht {
|
|
|
1008
1009
|
})) == null ? void 0 : ot.detail) == null ? void 0 : ct.annotations) || void 0
|
|
1009
1010
|
},
|
|
1010
1011
|
environment: e.environment ?? this.resolveFallbackEnvironment(e, u),
|
|
1011
|
-
replayWindow:
|
|
1012
|
+
replayWindow: b,
|
|
1012
1013
|
timeline: u,
|
|
1013
|
-
replay:
|
|
1014
|
+
replay: g,
|
|
1014
1015
|
diagnostics: {
|
|
1015
1016
|
droppedEvents: k,
|
|
1016
|
-
droppedEventsUnknown: I ||
|
|
1017
|
+
droppedEventsUnknown: I || r.size > 0 && k === 0,
|
|
1017
1018
|
storageBytes: m,
|
|
1018
|
-
degraded:
|
|
1019
|
-
degradedReasons: [...
|
|
1019
|
+
degraded: r.size > 0,
|
|
1020
|
+
degradedReasons: [...r]
|
|
1020
1021
|
}
|
|
1021
1022
|
};
|
|
1022
1023
|
}
|
|
@@ -1056,7 +1057,7 @@ class ht {
|
|
|
1056
1057
|
this.finalizeTimer && (clearTimeout(this.finalizeTimer), this.finalizeTimer = null), this.pendingIncident = null, this.recoveredBaseIncidentId = void 0, this.baseRecoveredDroppedEvents = 0, this.hasExtendedOnce = !1;
|
|
1057
1058
|
}
|
|
1058
1059
|
}
|
|
1059
|
-
const
|
|
1060
|
+
const F = "__backtrack_tab_id__", q = "__backtrack_session_id__", Q = "__ffr_tab_id__", Z = "__ffr_session_id__", ut = "__backtrack_session_channel__";
|
|
1060
1061
|
let N = null;
|
|
1061
1062
|
const G = /* @__PURE__ */ new Set();
|
|
1062
1063
|
function L(d) {
|
|
@@ -1070,13 +1071,13 @@ function L(d) {
|
|
|
1070
1071
|
}
|
|
1071
1072
|
function pt(d, t) {
|
|
1072
1073
|
G.add(d), d.addEventListener("message", (e) => {
|
|
1073
|
-
const
|
|
1074
|
-
if (
|
|
1074
|
+
const r = e.data;
|
|
1075
|
+
if (r && r.type === "CLAIM_TAB_ID" && r.tabId === t)
|
|
1075
1076
|
try {
|
|
1076
1077
|
d.postMessage({
|
|
1077
1078
|
type: "TAB_ID_COLLISION",
|
|
1078
1079
|
tabId: t,
|
|
1079
|
-
claimId:
|
|
1080
|
+
claimId: r.claimId
|
|
1080
1081
|
});
|
|
1081
1082
|
} catch {
|
|
1082
1083
|
}
|
|
@@ -1110,23 +1111,23 @@ function zt(d) {
|
|
|
1110
1111
|
tabId: L("tab"),
|
|
1111
1112
|
sessionId: L("sess")
|
|
1112
1113
|
};
|
|
1113
|
-
let e = t.getItem(
|
|
1114
|
+
let e = t.getItem(F) || t.getItem(Q);
|
|
1114
1115
|
if (!e) {
|
|
1115
1116
|
e = L("tab");
|
|
1116
1117
|
try {
|
|
1117
|
-
t.setItem(
|
|
1118
|
+
t.setItem(F, e);
|
|
1118
1119
|
} catch {
|
|
1119
1120
|
}
|
|
1120
1121
|
}
|
|
1121
|
-
let
|
|
1122
|
-
if (!
|
|
1123
|
-
|
|
1122
|
+
let r = t.getItem(q) || t.getItem(Z);
|
|
1123
|
+
if (!r) {
|
|
1124
|
+
r = L("sess");
|
|
1124
1125
|
try {
|
|
1125
|
-
t.setItem(q,
|
|
1126
|
+
t.setItem(q, r);
|
|
1126
1127
|
} catch {
|
|
1127
1128
|
}
|
|
1128
1129
|
}
|
|
1129
|
-
return { tabId: e, sessionId:
|
|
1130
|
+
return { tabId: e, sessionId: r };
|
|
1130
1131
|
}
|
|
1131
1132
|
async function Ht(d) {
|
|
1132
1133
|
const t = (d == null ? void 0 : d.storage) || (typeof window < "u" ? window.sessionStorage : void 0);
|
|
@@ -1137,38 +1138,38 @@ async function Ht(d) {
|
|
|
1137
1138
|
};
|
|
1138
1139
|
return N = u, u;
|
|
1139
1140
|
}
|
|
1140
|
-
let e = t.getItem(
|
|
1141
|
-
const
|
|
1141
|
+
let e = t.getItem(F) || t.getItem(Q), r = t.getItem(q) || t.getItem(Z);
|
|
1142
|
+
const n = !(d != null && d.disableBroadcastChannel) && (!!(d != null && d.channel) || typeof BroadcastChannel < "u");
|
|
1142
1143
|
if (!e) {
|
|
1143
|
-
e = L("tab"),
|
|
1144
|
+
e = L("tab"), r = r || L("sess");
|
|
1144
1145
|
try {
|
|
1145
|
-
t.setItem(
|
|
1146
|
+
t.setItem(F, e), t.setItem(q, r);
|
|
1146
1147
|
} catch {
|
|
1147
1148
|
}
|
|
1148
|
-
if (
|
|
1149
|
+
if (n)
|
|
1149
1150
|
try {
|
|
1150
1151
|
const p = (d == null ? void 0 : d.channel) || new BroadcastChannel((d == null ? void 0 : d.channelName) || ut);
|
|
1151
1152
|
pt(p, e);
|
|
1152
1153
|
} catch {
|
|
1153
1154
|
}
|
|
1154
|
-
const u = { tabId: e, sessionId:
|
|
1155
|
+
const u = { tabId: e, sessionId: r };
|
|
1155
1156
|
return N = u, u;
|
|
1156
1157
|
}
|
|
1157
|
-
if (!
|
|
1158
|
-
|
|
1158
|
+
if (!n) {
|
|
1159
|
+
r = r || L("sess");
|
|
1159
1160
|
try {
|
|
1160
|
-
t.setItem(q,
|
|
1161
|
+
t.setItem(q, r);
|
|
1161
1162
|
} catch {
|
|
1162
1163
|
}
|
|
1163
|
-
const u = { tabId: e, sessionId:
|
|
1164
|
+
const u = { tabId: e, sessionId: r };
|
|
1164
1165
|
return N = u, u;
|
|
1165
1166
|
}
|
|
1166
1167
|
let i = null;
|
|
1167
1168
|
try {
|
|
1168
1169
|
i = (d == null ? void 0 : d.channel) || new BroadcastChannel((d == null ? void 0 : d.channelName) || ut);
|
|
1169
1170
|
} catch {
|
|
1170
|
-
|
|
1171
|
-
const u = { tabId: e, sessionId:
|
|
1171
|
+
r = r || L("sess");
|
|
1172
|
+
const u = { tabId: e, sessionId: r };
|
|
1172
1173
|
return N = u, u;
|
|
1173
1174
|
}
|
|
1174
1175
|
const a = L("claim"), s = (d == null ? void 0 : d.timeoutMs) ?? 50;
|
|
@@ -1191,27 +1192,27 @@ async function Ht(d) {
|
|
|
1191
1192
|
i.removeEventListener("message", c);
|
|
1192
1193
|
}
|
|
1193
1194
|
if (o) {
|
|
1194
|
-
e = L("tab"),
|
|
1195
|
+
e = L("tab"), r = L("sess");
|
|
1195
1196
|
try {
|
|
1196
|
-
t.setItem(
|
|
1197
|
+
t.setItem(F, e), t.setItem(q, r);
|
|
1197
1198
|
} catch {
|
|
1198
1199
|
}
|
|
1199
|
-
} else if (!
|
|
1200
|
-
|
|
1200
|
+
} else if (!r) {
|
|
1201
|
+
r = L("sess");
|
|
1201
1202
|
try {
|
|
1202
|
-
t.setItem(q,
|
|
1203
|
+
t.setItem(q, r);
|
|
1203
1204
|
} catch {
|
|
1204
1205
|
}
|
|
1205
1206
|
}
|
|
1206
1207
|
pt(i, e);
|
|
1207
|
-
const h = { tabId: e, sessionId:
|
|
1208
|
+
const h = { tabId: e, sessionId: r };
|
|
1208
1209
|
return N = h, h;
|
|
1209
1210
|
}
|
|
1210
1211
|
function ue(d) {
|
|
1211
1212
|
const t = d || (typeof window < "u" ? window.sessionStorage : void 0);
|
|
1212
1213
|
if (t)
|
|
1213
1214
|
try {
|
|
1214
|
-
t.removeItem(
|
|
1215
|
+
t.removeItem(F), t.removeItem(q), t.removeItem(Q), t.removeItem(Z);
|
|
1215
1216
|
} catch {
|
|
1216
1217
|
}
|
|
1217
1218
|
return N = null, tt(), zt(d);
|
|
@@ -1242,7 +1243,7 @@ const _t = /* @__PURE__ */ new Set([
|
|
|
1242
1243
|
"refreshtoken",
|
|
1243
1244
|
"apikey",
|
|
1244
1245
|
"pin"
|
|
1245
|
-
]), $t = /Bearer\s+[A-Za-z0-9\-_=.]+/gi, Ot = /Basic\s+[A-Za-z0-9+/=]+/gi, qt = /eyJ[A-Za-z0-9-_=]+\.eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]*/gi, Nt = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
|
|
1246
|
+
]), $t = /Bearer\s+[A-Za-z0-9\-_=.]+/gi, Ot = /Basic\s+[A-Za-z0-9+/=]+/gi, qt = /eyJ[A-Za-z0-9-_=]+\.eyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_.+/=]*/gi, Nt = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, Ft = /\b\d{3}\.?\d{3}\.?\d{3}-?\d{2}\b/g, jt = /\b\d{2}\.?\d{3}\.?\d{3}\/?\d{4}-?\d{2}\b/g, Ut = /\b(?:\d[ -]*?){13,19}\b/g, Wt = /(?:\+?55\s?)?(?:\(?\d{2}\)?\s?)?(?:9\d{4}|\d{4})[ -]?\d{4}/g, Gt = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, Vt = /\b\d{6,}\b/g, Xt = {
|
|
1246
1247
|
maxDepth: 4,
|
|
1247
1248
|
maxKeys: 50,
|
|
1248
1249
|
maxItems: 50,
|
|
@@ -1253,10 +1254,10 @@ function V(d, t) {
|
|
|
1253
1254
|
const e = new URL(d, "http://localhost");
|
|
1254
1255
|
if (t)
|
|
1255
1256
|
return t(e);
|
|
1256
|
-
let
|
|
1257
|
-
|
|
1258
|
-
const
|
|
1259
|
-
return !d.startsWith("http://") && !d.startsWith("https://") ? `${
|
|
1257
|
+
let r = e.pathname;
|
|
1258
|
+
r = r.replace(Gt, ":id"), r = r.replace(Vt, ":id");
|
|
1259
|
+
const n = Array.from(new Set(e.searchParams.keys())).sort(), i = n.length > 0 ? `?${n.join("&")}` : "";
|
|
1260
|
+
return !d.startsWith("http://") && !d.startsWith("https://") ? `${r}${i}` : `${e.origin}${r}${i}`;
|
|
1260
1261
|
} catch {
|
|
1261
1262
|
return "[INVALID_URL]";
|
|
1262
1263
|
}
|
|
@@ -1264,7 +1265,7 @@ function V(d, t) {
|
|
|
1264
1265
|
function D(d) {
|
|
1265
1266
|
if (!d || typeof d != "string") return d;
|
|
1266
1267
|
let t = d;
|
|
1267
|
-
return t = t.replace($t, "Bearer [REDACTED_TOKEN]"), t = t.replace(Ot, "Basic [REDACTED_BASIC]"), t = t.replace(qt, "[REDACTED_JWT]"), t = t.replace(Nt, "[REDACTED_EMAIL]"), t = t.replace(
|
|
1268
|
+
return t = t.replace($t, "Bearer [REDACTED_TOKEN]"), t = t.replace(Ot, "Basic [REDACTED_BASIC]"), t = t.replace(qt, "[REDACTED_JWT]"), t = t.replace(Nt, "[REDACTED_EMAIL]"), t = t.replace(Ft, "[REDACTED_CPF]"), t = t.replace(jt, "[REDACTED_CNPJ]"), t = t.replace(Ut, "[REDACTED_CARD]"), t = t.replace(Wt, "[REDACTED_PHONE]"), t;
|
|
1268
1269
|
}
|
|
1269
1270
|
function Yt(d) {
|
|
1270
1271
|
const t = d.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -1273,8 +1274,8 @@ function Yt(d) {
|
|
|
1273
1274
|
return !1;
|
|
1274
1275
|
}
|
|
1275
1276
|
function wt(d, t) {
|
|
1276
|
-
const e = { ...Xt, ...t },
|
|
1277
|
-
function
|
|
1277
|
+
const e = { ...Xt, ...t }, r = /* @__PURE__ */ new WeakSet();
|
|
1278
|
+
function n(i, a) {
|
|
1278
1279
|
try {
|
|
1279
1280
|
if (i == null || typeof i == "boolean")
|
|
1280
1281
|
return i;
|
|
@@ -1291,9 +1292,9 @@ function wt(d, t) {
|
|
|
1291
1292
|
return s.length > e.maxStringLength && (s = `${s.substring(0, e.maxStringLength)}... [TRUNCATED]`), s;
|
|
1292
1293
|
}
|
|
1293
1294
|
if (typeof i == "object") {
|
|
1294
|
-
if (
|
|
1295
|
+
if (r.has(i))
|
|
1295
1296
|
return "[CIRCULAR]";
|
|
1296
|
-
if (
|
|
1297
|
+
if (r.add(i), a >= e.maxDepth)
|
|
1297
1298
|
return "[MAX_DEPTH]";
|
|
1298
1299
|
if (i instanceof Error)
|
|
1299
1300
|
return {
|
|
@@ -1311,8 +1312,8 @@ function wt(d, t) {
|
|
|
1311
1312
|
}
|
|
1312
1313
|
if (Array.isArray(i)) {
|
|
1313
1314
|
const u = [], p = Math.min(i.length, e.maxItems);
|
|
1314
|
-
for (let
|
|
1315
|
-
u.push(
|
|
1315
|
+
for (let g = 0; g < p; g++)
|
|
1316
|
+
u.push(n(i[g], a + 1));
|
|
1316
1317
|
return i.length > e.maxItems && u.push(`... [${i.length - e.maxItems} more items TRUNCATED]`), u;
|
|
1317
1318
|
}
|
|
1318
1319
|
const s = i, o = {}, c = Object.keys(s), h = Math.min(c.length, e.maxKeys);
|
|
@@ -1322,7 +1323,7 @@ function wt(d, t) {
|
|
|
1322
1323
|
o[p] = "[REDACTED]";
|
|
1323
1324
|
else
|
|
1324
1325
|
try {
|
|
1325
|
-
o[p] =
|
|
1326
|
+
o[p] = n(s[p], a + 1);
|
|
1326
1327
|
} catch {
|
|
1327
1328
|
o[p] = "[GETTER_ERROR]";
|
|
1328
1329
|
}
|
|
@@ -1335,7 +1336,7 @@ function wt(d, t) {
|
|
|
1335
1336
|
}
|
|
1336
1337
|
}
|
|
1337
1338
|
try {
|
|
1338
|
-
return
|
|
1339
|
+
return n(d, 0);
|
|
1339
1340
|
} catch {
|
|
1340
1341
|
return "[SERIALIZATION_FAILED]";
|
|
1341
1342
|
}
|
|
@@ -1345,8 +1346,8 @@ function U(d, t = 64 * 1024) {
|
|
|
1345
1346
|
let e = d;
|
|
1346
1347
|
e.length > t && (e = `${e.substring(0, t)}... [TRUNCATED ${d.length - t} BYTES]`);
|
|
1347
1348
|
try {
|
|
1348
|
-
const
|
|
1349
|
-
return JSON.stringify(
|
|
1349
|
+
const r = JSON.parse(e), n = wt(r, { maxStringLength: 2e3 });
|
|
1350
|
+
return JSON.stringify(n, null, 2);
|
|
1350
1351
|
} catch {
|
|
1351
1352
|
return D(e);
|
|
1352
1353
|
}
|
|
@@ -1356,8 +1357,8 @@ function W(d) {
|
|
|
1356
1357
|
const t = {};
|
|
1357
1358
|
let e = [];
|
|
1358
1359
|
typeof Headers < "u" && d instanceof Headers ? e = Array.from(d.entries()) : Array.isArray(d) ? e = d : typeof d == "object" && (e = Object.entries(d));
|
|
1359
|
-
for (const [
|
|
1360
|
-
const i = String(
|
|
1360
|
+
for (const [r, n] of e) {
|
|
1361
|
+
const i = String(r), a = String(n), s = i.toLowerCase();
|
|
1361
1362
|
s.includes("auth") || s.includes("cookie") || s.includes("token") || s.includes("secret") || s.includes("key") ? t[i] = "[REDACTED]" : t[i] = D(a);
|
|
1362
1363
|
}
|
|
1363
1364
|
return Object.keys(t).length > 0 ? t : void 0;
|
|
@@ -1385,21 +1386,21 @@ class Jt {
|
|
|
1385
1386
|
this.handleConsole("error", this.originalError, t);
|
|
1386
1387
|
}, console.log = this.wrappedLog, console.warn = this.wrappedWarn, console.error = this.wrappedError);
|
|
1387
1388
|
}
|
|
1388
|
-
handleConsole(t, e,
|
|
1389
|
+
handleConsole(t, e, r) {
|
|
1389
1390
|
try {
|
|
1390
|
-
e.apply(console,
|
|
1391
|
+
e.apply(console, r);
|
|
1391
1392
|
} catch {
|
|
1392
1393
|
}
|
|
1393
1394
|
if (!(this.isInsideHook || !this.isRecording)) {
|
|
1394
1395
|
this.isInsideHook = !0;
|
|
1395
1396
|
try {
|
|
1396
|
-
const
|
|
1397
|
+
const n = r.map((a) => wt(a)), i = {
|
|
1397
1398
|
id: `con_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1398
1399
|
timestamp: Date.now(),
|
|
1399
1400
|
sequence: this.sequenceProvider(),
|
|
1400
1401
|
type: "console",
|
|
1401
1402
|
level: t,
|
|
1402
|
-
args:
|
|
1403
|
+
args: n
|
|
1403
1404
|
};
|
|
1404
1405
|
this.writer.addTimelineEvent(i);
|
|
1405
1406
|
} catch {
|
|
@@ -1413,14 +1414,14 @@ class Jt {
|
|
|
1413
1414
|
}
|
|
1414
1415
|
}
|
|
1415
1416
|
class Kt {
|
|
1416
|
-
constructor(t, e,
|
|
1417
|
+
constructor(t, e, r) {
|
|
1417
1418
|
l(this, "writer");
|
|
1418
1419
|
l(this, "incidentManager");
|
|
1419
1420
|
l(this, "sequenceProvider");
|
|
1420
1421
|
l(this, "isRecording", !1);
|
|
1421
1422
|
l(this, "errorHandler");
|
|
1422
1423
|
l(this, "rejectionHandler");
|
|
1423
|
-
this.writer = t, this.incidentManager = e, this.sequenceProvider =
|
|
1424
|
+
this.writer = t, this.incidentManager = e, this.sequenceProvider = r;
|
|
1424
1425
|
}
|
|
1425
1426
|
start() {
|
|
1426
1427
|
this.isRecording || (this.isRecording = !0, !(typeof window > "u") && (this.errorHandler = (t) => {
|
|
@@ -1432,11 +1433,11 @@ class Kt {
|
|
|
1432
1433
|
handleGlobalError(t) {
|
|
1433
1434
|
if (this.isRecording)
|
|
1434
1435
|
try {
|
|
1435
|
-
const e = t.error instanceof Error ? t.error : null,
|
|
1436
|
+
const e = t.error instanceof Error ? t.error : null, r = (e == null ? void 0 : e.name) || "Error", n = D(t.message || (e == null ? void 0 : e.message) || "Unknown error"), i = e != null && e.stack ? D(e.stack) : void 0, a = t.filename || void 0, s = t.lineno || void 0, o = t.colno || void 0;
|
|
1436
1437
|
this.recordAndTriggerError({
|
|
1437
1438
|
source: "window",
|
|
1438
|
-
name:
|
|
1439
|
-
message:
|
|
1439
|
+
name: r,
|
|
1440
|
+
message: n,
|
|
1440
1441
|
stack: i,
|
|
1441
1442
|
filename: a,
|
|
1442
1443
|
lineno: s,
|
|
@@ -1450,11 +1451,11 @@ class Kt {
|
|
|
1450
1451
|
if (this.isRecording)
|
|
1451
1452
|
try {
|
|
1452
1453
|
const e = t.reason;
|
|
1453
|
-
let
|
|
1454
|
-
e instanceof Error ? (
|
|
1454
|
+
let r = "UnhandledRejection", n = "Promise rejeitada", i;
|
|
1455
|
+
e instanceof Error ? (r = e.name, n = D(e.message), i = e.stack ? D(e.stack) : void 0) : typeof e == "string" ? n = D(e) : e && typeof e == "object" && (n = D(JSON.stringify(e))), this.recordAndTriggerError({
|
|
1455
1456
|
source: "unhandledrejection",
|
|
1456
|
-
name:
|
|
1457
|
-
message:
|
|
1457
|
+
name: r,
|
|
1458
|
+
message: n,
|
|
1458
1459
|
stack: i
|
|
1459
1460
|
}).catch(() => {
|
|
1460
1461
|
});
|
|
@@ -1467,13 +1468,13 @@ class Kt {
|
|
|
1467
1468
|
captureException(t, e) {
|
|
1468
1469
|
if (this.isRecording)
|
|
1469
1470
|
try {
|
|
1470
|
-
let
|
|
1471
|
-
t instanceof Error ? (
|
|
1471
|
+
let r = "Error", n = "Exceção capturada", i, a;
|
|
1472
|
+
t instanceof Error ? (r = t.name, n = D(t.message), i = t.stack ? D(t.stack) : void 0) : typeof t == "string" && (n = D(t)), e != null && e.componentStack && (a = D(e.componentStack));
|
|
1472
1473
|
const s = (e == null ? void 0 : e.source) === "react" ? "react" : "manual";
|
|
1473
1474
|
return this.recordAndTriggerError({
|
|
1474
1475
|
source: s,
|
|
1475
|
-
name:
|
|
1476
|
-
message:
|
|
1476
|
+
name: r,
|
|
1477
|
+
message: n,
|
|
1477
1478
|
stack: i,
|
|
1478
1479
|
componentStack: a
|
|
1479
1480
|
}).catch(() => {
|
|
@@ -1483,7 +1484,7 @@ class Kt {
|
|
|
1483
1484
|
}
|
|
1484
1485
|
recordAndTriggerError(t) {
|
|
1485
1486
|
var s;
|
|
1486
|
-
const e = Date.now(),
|
|
1487
|
+
const e = Date.now(), r = {
|
|
1487
1488
|
id: `err_${e}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1488
1489
|
timestamp: e,
|
|
1489
1490
|
sequence: this.sequenceProvider(),
|
|
@@ -1497,9 +1498,9 @@ class Kt {
|
|
|
1497
1498
|
colno: t.colno,
|
|
1498
1499
|
componentStack: t.componentStack
|
|
1499
1500
|
};
|
|
1500
|
-
this.writer.addTimelineEvent(
|
|
1501
|
-
const
|
|
1502
|
-
`)[1]) == null ? void 0 : s.trim()) || "", i = `${t.name}:${t.message}:${
|
|
1501
|
+
this.writer.addTimelineEvent(r);
|
|
1502
|
+
const n = t.stack && ((s = t.stack.split(`
|
|
1503
|
+
`)[1]) == null ? void 0 : s.trim()) || "", i = `${t.name}:${t.message}:${n}`, a = t.source === "react" ? "react" : t.source === "unhandledrejection" ? "unhandledrejection" : "error";
|
|
1503
1504
|
return this.incidentManager.trigger(a, {
|
|
1504
1505
|
id: `trig_${e}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1505
1506
|
timestamp: e,
|
|
@@ -1517,7 +1518,7 @@ class Kt {
|
|
|
1517
1518
|
}
|
|
1518
1519
|
}
|
|
1519
1520
|
class Qt {
|
|
1520
|
-
constructor(t, e,
|
|
1521
|
+
constructor(t, e, r, n) {
|
|
1521
1522
|
l(this, "writer");
|
|
1522
1523
|
l(this, "incidentManager");
|
|
1523
1524
|
l(this, "sequenceProvider");
|
|
@@ -1529,12 +1530,12 @@ class Qt {
|
|
|
1529
1530
|
l(this, "originalXHRSend", null);
|
|
1530
1531
|
l(this, "originalXHRSetHeader", null);
|
|
1531
1532
|
l(this, "xhrMetadata", /* @__PURE__ */ new WeakMap());
|
|
1532
|
-
this.writer = t, this.incidentManager = e, this.sequenceProvider =
|
|
1533
|
-
captureHttpStatus: (
|
|
1534
|
-
ignoredUrls: (
|
|
1535
|
-
sanitizeUrlCallback:
|
|
1536
|
-
capturePayloads: (
|
|
1537
|
-
maxPayloadSize: Math.max(0, (
|
|
1533
|
+
this.writer = t, this.incidentManager = e, this.sequenceProvider = r, this.config = {
|
|
1534
|
+
captureHttpStatus: (n == null ? void 0 : n.captureHttpStatus) ?? [500, 502, 503, 504],
|
|
1535
|
+
ignoredUrls: (n == null ? void 0 : n.ignoredUrls) ?? [],
|
|
1536
|
+
sanitizeUrlCallback: n == null ? void 0 : n.sanitizeUrlCallback,
|
|
1537
|
+
capturePayloads: (n == null ? void 0 : n.capturePayloads) ?? !1,
|
|
1538
|
+
maxPayloadSize: Math.max(0, (n == null ? void 0 : n.maxPayloadSize) ?? 64 * 1024)
|
|
1538
1539
|
};
|
|
1539
1540
|
}
|
|
1540
1541
|
start() {
|
|
@@ -1553,38 +1554,38 @@ class Qt {
|
|
|
1553
1554
|
if (typeof window > "u" || !window.fetch) return;
|
|
1554
1555
|
this.originalFetch = window.fetch;
|
|
1555
1556
|
const t = this;
|
|
1556
|
-
this.wrappedFetch = async function(e,
|
|
1557
|
+
this.wrappedFetch = async function(e, r) {
|
|
1557
1558
|
var p;
|
|
1558
|
-
let
|
|
1559
|
+
let n = "", i = (r == null ? void 0 : r.method) || "GET", a = r == null ? void 0 : r.headers, s;
|
|
1559
1560
|
if (typeof e == "string")
|
|
1560
|
-
|
|
1561
|
+
n = e;
|
|
1561
1562
|
else if (e instanceof URL)
|
|
1562
|
-
|
|
1563
|
+
n = e.href;
|
|
1563
1564
|
else if (e && typeof e.url == "string") {
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1565
|
+
const g = e;
|
|
1566
|
+
n = g.url, i = g.method || i, a = a || g.headers;
|
|
1566
1567
|
}
|
|
1567
|
-
if (t.config.capturePayloads && (
|
|
1568
|
+
if (t.config.capturePayloads && (r != null && r.body))
|
|
1568
1569
|
try {
|
|
1569
|
-
typeof
|
|
1570
|
+
typeof r.body == "string" ? s = r.body : typeof URLSearchParams < "u" && r.body instanceof URLSearchParams && (s = r.body.toString());
|
|
1570
1571
|
} catch {
|
|
1571
1572
|
}
|
|
1572
|
-
if (!t.isRecording || t.shouldIgnoreUrl(
|
|
1573
|
-
return t.originalFetch.call(this, e,
|
|
1574
|
-
const o = Date.now(), c = V(
|
|
1573
|
+
if (!t.isRecording || t.shouldIgnoreUrl(n))
|
|
1574
|
+
return t.originalFetch.call(this, e, r);
|
|
1575
|
+
const o = Date.now(), c = V(n, t.config.sanitizeUrlCallback), h = W(a), u = t.config.capturePayloads && s ? U(s, t.config.maxPayloadSize) : void 0;
|
|
1575
1576
|
try {
|
|
1576
|
-
const
|
|
1577
|
+
const g = await t.originalFetch.call(this, e, r), b = Date.now() - o, f = g.status, m = f >= 400 ? "error" : "success";
|
|
1577
1578
|
let k;
|
|
1578
1579
|
try {
|
|
1579
|
-
k = W(
|
|
1580
|
+
k = W(g.headers);
|
|
1580
1581
|
} catch {
|
|
1581
1582
|
}
|
|
1582
1583
|
let I;
|
|
1583
1584
|
if (t.config.capturePayloads)
|
|
1584
1585
|
try {
|
|
1585
|
-
const y = ((p =
|
|
1586
|
+
const y = ((p = g.headers) == null ? void 0 : p.get("content-type")) || "";
|
|
1586
1587
|
if (y.includes("json") || y.includes("text") || y.includes("xml") || y.includes("javascript") || y.includes("form")) {
|
|
1587
|
-
const E = await
|
|
1588
|
+
const E = await g.clone().text();
|
|
1588
1589
|
I = U(E, t.config.maxPayloadSize);
|
|
1589
1590
|
}
|
|
1590
1591
|
} catch {
|
|
@@ -1593,65 +1594,65 @@ class Qt {
|
|
|
1593
1594
|
method: i.toUpperCase(),
|
|
1594
1595
|
url: c,
|
|
1595
1596
|
status: f,
|
|
1596
|
-
durationMs:
|
|
1597
|
+
durationMs: b,
|
|
1597
1598
|
result: m,
|
|
1598
1599
|
requestHeaders: h,
|
|
1599
1600
|
requestBody: u,
|
|
1600
1601
|
responseHeaders: k,
|
|
1601
1602
|
responseBody: I
|
|
1602
|
-
}),
|
|
1603
|
-
} catch (
|
|
1604
|
-
const
|
|
1603
|
+
}), g;
|
|
1604
|
+
} catch (g) {
|
|
1605
|
+
const b = Date.now() - o, m = g instanceof DOMException && g.name === "AbortError" ? "abort" : "error";
|
|
1605
1606
|
throw t.recordNetworkEvent({
|
|
1606
1607
|
method: i.toUpperCase(),
|
|
1607
1608
|
url: c,
|
|
1608
1609
|
status: 0,
|
|
1609
|
-
durationMs:
|
|
1610
|
+
durationMs: b,
|
|
1610
1611
|
result: m,
|
|
1611
1612
|
requestHeaders: h,
|
|
1612
1613
|
requestBody: u
|
|
1613
|
-
}),
|
|
1614
|
+
}), g;
|
|
1614
1615
|
}
|
|
1615
1616
|
}, window.fetch = this.wrappedFetch;
|
|
1616
1617
|
}
|
|
1617
1618
|
instrumentXHR() {
|
|
1618
1619
|
if (typeof window > "u" || !window.XMLHttpRequest) return;
|
|
1619
1620
|
const t = this, e = window.XMLHttpRequest.prototype;
|
|
1620
|
-
this.originalXHROpen = e.open, this.originalXHRSend = e.send, this.originalXHRSetHeader = e.setRequestHeader, e.open = function(
|
|
1621
|
+
this.originalXHROpen = e.open, this.originalXHRSend = e.send, this.originalXHRSetHeader = e.setRequestHeader, e.open = function(r, n, i = !0, a, s) {
|
|
1621
1622
|
if (t.isRecording) {
|
|
1622
|
-
const o = typeof
|
|
1623
|
+
const o = typeof n == "string" ? n : n.href;
|
|
1623
1624
|
t.xhrMetadata.set(this, {
|
|
1624
|
-
method: (
|
|
1625
|
+
method: (r || "GET").toUpperCase(),
|
|
1625
1626
|
url: o,
|
|
1626
1627
|
startTime: 0,
|
|
1627
1628
|
requestHeaders: {}
|
|
1628
1629
|
});
|
|
1629
1630
|
}
|
|
1630
|
-
return t.originalXHROpen.call(this,
|
|
1631
|
-
}, e.setRequestHeader = function(
|
|
1631
|
+
return t.originalXHROpen.call(this, r, n, i, a, s);
|
|
1632
|
+
}, e.setRequestHeader = function(r, n) {
|
|
1632
1633
|
const i = t.xhrMetadata.get(this);
|
|
1633
|
-
return i && i.requestHeaders && (i.requestHeaders[
|
|
1634
|
-
}, e.send = function(
|
|
1635
|
-
const
|
|
1636
|
-
if (t.isRecording &&
|
|
1637
|
-
|
|
1638
|
-
const i = V(
|
|
1639
|
-
t.config.capturePayloads && typeof
|
|
1634
|
+
return i && i.requestHeaders && (i.requestHeaders[r] = n), t.originalXHRSetHeader.call(this, r, n);
|
|
1635
|
+
}, e.send = function(r) {
|
|
1636
|
+
const n = t.xhrMetadata.get(this);
|
|
1637
|
+
if (t.isRecording && n && !t.shouldIgnoreUrl(n.url)) {
|
|
1638
|
+
n.startTime = Date.now();
|
|
1639
|
+
const i = V(n.url, t.config.sanitizeUrlCallback);
|
|
1640
|
+
t.config.capturePayloads && typeof r == "string" && (n.requestBody = r);
|
|
1640
1641
|
let a = !1;
|
|
1641
1642
|
const s = (o, c) => {
|
|
1642
1643
|
if (a) return;
|
|
1643
1644
|
a = !0;
|
|
1644
|
-
const h =
|
|
1645
|
+
const h = n.startTime ? Date.now() - n.startTime : 0;
|
|
1645
1646
|
let u;
|
|
1646
1647
|
try {
|
|
1647
|
-
const
|
|
1648
|
-
if (
|
|
1649
|
-
const
|
|
1650
|
-
for (const f of
|
|
1648
|
+
const g = this.getAllResponseHeaders();
|
|
1649
|
+
if (g) {
|
|
1650
|
+
const b = {};
|
|
1651
|
+
for (const f of g.trim().split(/[\r\n]+/)) {
|
|
1651
1652
|
const m = f.split(": "), k = m.shift(), I = m.join(": ");
|
|
1652
|
-
k && (
|
|
1653
|
+
k && (b[k] = I);
|
|
1653
1654
|
}
|
|
1654
|
-
u = W(
|
|
1655
|
+
u = W(b);
|
|
1655
1656
|
}
|
|
1656
1657
|
} catch {
|
|
1657
1658
|
}
|
|
@@ -1662,13 +1663,13 @@ class Qt {
|
|
|
1662
1663
|
} catch {
|
|
1663
1664
|
}
|
|
1664
1665
|
t.recordNetworkEvent({
|
|
1665
|
-
method:
|
|
1666
|
+
method: n.method,
|
|
1666
1667
|
url: i,
|
|
1667
1668
|
status: c,
|
|
1668
1669
|
durationMs: h,
|
|
1669
1670
|
result: o,
|
|
1670
|
-
requestHeaders: W(
|
|
1671
|
-
requestBody: t.config.capturePayloads &&
|
|
1671
|
+
requestHeaders: W(n.requestHeaders),
|
|
1672
|
+
requestBody: t.config.capturePayloads && n.requestBody ? U(n.requestBody, t.config.maxPayloadSize) : void 0,
|
|
1672
1673
|
responseHeaders: u,
|
|
1673
1674
|
responseBody: p
|
|
1674
1675
|
});
|
|
@@ -1682,16 +1683,16 @@ class Qt {
|
|
|
1682
1683
|
{ once: !0 }
|
|
1683
1684
|
), this.addEventListener("error", () => s("error", this.status || 0), { once: !0 }), this.addEventListener("timeout", () => s("timeout", 0), { once: !0 }), this.addEventListener("abort", () => s("abort", 0), { once: !0 });
|
|
1684
1685
|
try {
|
|
1685
|
-
return t.originalXHRSend.call(this,
|
|
1686
|
+
return t.originalXHRSend.call(this, r);
|
|
1686
1687
|
} catch (o) {
|
|
1687
1688
|
throw s("error", 0), o;
|
|
1688
1689
|
}
|
|
1689
1690
|
}
|
|
1690
|
-
return t.originalXHRSend.call(this,
|
|
1691
|
+
return t.originalXHRSend.call(this, r);
|
|
1691
1692
|
};
|
|
1692
1693
|
}
|
|
1693
1694
|
recordNetworkEvent(t) {
|
|
1694
|
-
const e = Date.now(),
|
|
1695
|
+
const e = Date.now(), r = {
|
|
1695
1696
|
id: `net_${e}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1696
1697
|
timestamp: e,
|
|
1697
1698
|
sequence: this.sequenceProvider(),
|
|
@@ -1706,7 +1707,7 @@ class Qt {
|
|
|
1706
1707
|
responseHeaders: t.responseHeaders,
|
|
1707
1708
|
responseBody: t.responseBody
|
|
1708
1709
|
};
|
|
1709
|
-
this.writer.addTimelineEvent(
|
|
1710
|
+
this.writer.addTimelineEvent(r), (this.config.captureHttpStatus.includes(t.status) || t.status === 0 && t.result === "error") && this.incidentManager.trigger("http", {
|
|
1710
1711
|
id: `trig_http_${e}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1711
1712
|
timestamp: e,
|
|
1712
1713
|
type: "http",
|
|
@@ -1725,7 +1726,7 @@ class Qt {
|
|
|
1725
1726
|
}
|
|
1726
1727
|
}
|
|
1727
1728
|
class Zt {
|
|
1728
|
-
constructor(t, e,
|
|
1729
|
+
constructor(t, e, r) {
|
|
1729
1730
|
l(this, "writer");
|
|
1730
1731
|
l(this, "sequenceProvider");
|
|
1731
1732
|
l(this, "config");
|
|
@@ -1735,20 +1736,20 @@ class Zt {
|
|
|
1735
1736
|
l(this, "originalReplaceState", null);
|
|
1736
1737
|
l(this, "popstateHandler");
|
|
1737
1738
|
l(this, "hashchangeHandler");
|
|
1738
|
-
this.writer = t, this.sequenceProvider = e, this.config =
|
|
1739
|
+
this.writer = t, this.sequenceProvider = e, this.config = r || {};
|
|
1739
1740
|
}
|
|
1740
1741
|
start() {
|
|
1741
1742
|
if (this.isRecording || (this.isRecording = !0, typeof window > "u")) return;
|
|
1742
1743
|
this.currentUrl = window.location.href, this.recordNavigation("initial", this.currentUrl);
|
|
1743
1744
|
const t = this, e = window.history;
|
|
1744
|
-
this.originalPushState = e.pushState, this.originalReplaceState = e.replaceState, e.pushState = function(...
|
|
1745
|
-
t.originalPushState.apply(this,
|
|
1746
|
-
const
|
|
1747
|
-
t.recordNavigation("pushState",
|
|
1748
|
-
}, e.replaceState = function(...
|
|
1749
|
-
t.originalReplaceState.apply(this,
|
|
1750
|
-
const
|
|
1751
|
-
t.recordNavigation("replaceState",
|
|
1745
|
+
this.originalPushState = e.pushState, this.originalReplaceState = e.replaceState, e.pushState = function(...r) {
|
|
1746
|
+
t.originalPushState.apply(this, r);
|
|
1747
|
+
const n = window.location.href;
|
|
1748
|
+
t.recordNavigation("pushState", n);
|
|
1749
|
+
}, e.replaceState = function(...r) {
|
|
1750
|
+
t.originalReplaceState.apply(this, r);
|
|
1751
|
+
const n = window.location.href;
|
|
1752
|
+
t.recordNavigation("replaceState", n);
|
|
1752
1753
|
}, this.popstateHandler = () => {
|
|
1753
1754
|
this.recordNavigation("popstate", window.location.href);
|
|
1754
1755
|
}, window.addEventListener("popstate", this.popstateHandler), this.hashchangeHandler = () => {
|
|
@@ -1757,7 +1758,7 @@ class Zt {
|
|
|
1757
1758
|
}
|
|
1758
1759
|
recordNavigation(t, e) {
|
|
1759
1760
|
if (!this.isRecording) return;
|
|
1760
|
-
const
|
|
1761
|
+
const r = this.currentUrl ? V(this.currentUrl, this.config.sanitizeUrlCallback) : void 0, n = V(e, this.config.sanitizeUrlCallback);
|
|
1761
1762
|
this.currentUrl = e;
|
|
1762
1763
|
const i = {
|
|
1763
1764
|
id: `nav_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`,
|
|
@@ -1765,8 +1766,8 @@ class Zt {
|
|
|
1765
1766
|
sequence: this.sequenceProvider(),
|
|
1766
1767
|
type: "navigation",
|
|
1767
1768
|
kind: t,
|
|
1768
|
-
fromUrl:
|
|
1769
|
-
toUrl:
|
|
1769
|
+
fromUrl: r,
|
|
1770
|
+
toUrl: n
|
|
1770
1771
|
};
|
|
1771
1772
|
this.writer.addTimelineEvent(i);
|
|
1772
1773
|
}
|
|
@@ -1777,8 +1778,8 @@ class Zt {
|
|
|
1777
1778
|
function te(d) {
|
|
1778
1779
|
if (d === "*" || d === "/*")
|
|
1779
1780
|
return /^.*$/;
|
|
1780
|
-
const
|
|
1781
|
-
return new RegExp(`^${
|
|
1781
|
+
const r = (d.startsWith("/") || d.startsWith("*") ? d : `/${d}`).replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "§DOUBLE_STAR§").replace(/\*/g, "[^/]*").replace(/§DOUBLE_STAR§/g, ".*");
|
|
1782
|
+
return new RegExp(`^${r}/?(?:\\?|#|$)`, "i");
|
|
1782
1783
|
}
|
|
1783
1784
|
function ee(d, t) {
|
|
1784
1785
|
if (!t || t.length === 0)
|
|
@@ -1789,19 +1790,19 @@ function ee(d, t) {
|
|
|
1789
1790
|
} catch {
|
|
1790
1791
|
}
|
|
1791
1792
|
e.startsWith("/") || (e = `/${e}`);
|
|
1792
|
-
for (const
|
|
1793
|
-
if (typeof
|
|
1793
|
+
for (const r of t)
|
|
1794
|
+
if (typeof r == "function")
|
|
1794
1795
|
try {
|
|
1795
|
-
if (
|
|
1796
|
+
if (r(e)) return !0;
|
|
1796
1797
|
} catch {
|
|
1797
1798
|
}
|
|
1798
|
-
else if (
|
|
1799
|
-
if (
|
|
1800
|
-
} else if (typeof
|
|
1799
|
+
else if (r instanceof RegExp) {
|
|
1800
|
+
if (r.test(e)) return !0;
|
|
1801
|
+
} else if (typeof r == "string" && (r === e || te(r).test(e)))
|
|
1801
1802
|
return !0;
|
|
1802
1803
|
return !1;
|
|
1803
1804
|
}
|
|
1804
|
-
class
|
|
1805
|
+
class re {
|
|
1805
1806
|
constructor(t, e) {
|
|
1806
1807
|
l(this, "writer");
|
|
1807
1808
|
l(this, "config");
|
|
@@ -1829,29 +1830,29 @@ class ne {
|
|
|
1829
1830
|
".rr-block",
|
|
1830
1831
|
"[data-rr-ignore]",
|
|
1831
1832
|
"[data-backtrack-ignore]"
|
|
1832
|
-
].filter(Boolean).join(", "),
|
|
1833
|
+
].filter(Boolean).join(", "), r = [
|
|
1833
1834
|
t.maskTextSelector,
|
|
1834
1835
|
".backtrack-mask",
|
|
1835
1836
|
".ffr-mask",
|
|
1836
1837
|
"[data-backtrack-mask]"
|
|
1837
1838
|
].filter(Boolean).join(", ");
|
|
1838
1839
|
this.stopRecordFn = Ct({
|
|
1839
|
-
emit: (
|
|
1840
|
+
emit: (n, i) => {
|
|
1840
1841
|
if (this.isRecording)
|
|
1841
1842
|
try {
|
|
1842
|
-
const a =
|
|
1843
|
+
const a = n;
|
|
1843
1844
|
i && this.writer.flush(), this.writer.addReplayEvent(a);
|
|
1844
1845
|
} catch {
|
|
1845
1846
|
this.droppedEventsCount++;
|
|
1846
1847
|
}
|
|
1847
1848
|
},
|
|
1848
1849
|
maskAllInputs: t.maskAllInputs !== !1,
|
|
1849
|
-
maskTextSelector:
|
|
1850
|
+
maskTextSelector: r || void 0,
|
|
1850
1851
|
blockSelector: e || void 0,
|
|
1851
1852
|
blockClass: "backtrack-block",
|
|
1852
1853
|
ignoreClass: "backtrack-ignore",
|
|
1853
1854
|
maskTextClass: "backtrack-mask",
|
|
1854
|
-
maskTextFn: (
|
|
1855
|
+
maskTextFn: (n) => t.maskAllText || typeof window < "u" && ee(window.location.pathname, t.sensitiveRoutes) ? n.replace(/[^\s]/g, "*") : n,
|
|
1855
1856
|
checkoutEveryNms: this.config.checkoutEveryNms ?? 3e4,
|
|
1856
1857
|
sampling: {
|
|
1857
1858
|
mousemove: 50,
|
|
@@ -1879,14 +1880,14 @@ class ne {
|
|
|
1879
1880
|
}
|
|
1880
1881
|
}
|
|
1881
1882
|
}
|
|
1882
|
-
class
|
|
1883
|
-
constructor(t, e,
|
|
1883
|
+
class ne {
|
|
1884
|
+
constructor(t, e, r) {
|
|
1884
1885
|
l(this, "writer");
|
|
1885
1886
|
l(this, "sequenceProvider");
|
|
1886
1887
|
l(this, "observer", null);
|
|
1887
1888
|
l(this, "isRecording", !1);
|
|
1888
1889
|
l(this, "thresholdMs");
|
|
1889
|
-
this.writer = t, this.sequenceProvider = e, this.thresholdMs = (
|
|
1890
|
+
this.writer = t, this.sequenceProvider = e, this.thresholdMs = (r == null ? void 0 : r.longTaskThresholdMs) ?? 50;
|
|
1890
1891
|
}
|
|
1891
1892
|
start() {
|
|
1892
1893
|
if (!this.isRecording && (this.isRecording = !0, !(typeof PerformanceObserver > "u")))
|
|
@@ -1895,17 +1896,17 @@ class re {
|
|
|
1895
1896
|
return;
|
|
1896
1897
|
this.observer = new PerformanceObserver((e) => {
|
|
1897
1898
|
if (!this.isRecording) return;
|
|
1898
|
-
const
|
|
1899
|
-
for (const
|
|
1900
|
-
if (
|
|
1899
|
+
const r = e.getEntries();
|
|
1900
|
+
for (const n of r)
|
|
1901
|
+
if (n.duration >= this.thresholdMs) {
|
|
1901
1902
|
const i = Date.now(), a = {
|
|
1902
1903
|
id: `perf_${i}_${Math.random().toString(36).substring(2, 7)}`,
|
|
1903
1904
|
timestamp: i,
|
|
1904
1905
|
sequence: this.sequenceProvider(),
|
|
1905
1906
|
type: "performance",
|
|
1906
1907
|
metric: "longtask",
|
|
1907
|
-
durationMs: Math.round(
|
|
1908
|
-
details:
|
|
1908
|
+
durationMs: Math.round(n.duration),
|
|
1909
|
+
details: n.name || "Main thread blocked"
|
|
1909
1910
|
};
|
|
1910
1911
|
this.writer.addTimelineEvent(a);
|
|
1911
1912
|
}
|
|
@@ -1924,17 +1925,17 @@ class re {
|
|
|
1924
1925
|
}
|
|
1925
1926
|
}
|
|
1926
1927
|
}
|
|
1927
|
-
async function
|
|
1928
|
+
async function gt(d, t) {
|
|
1928
1929
|
if (!t || !t.trim())
|
|
1929
1930
|
throw new Error('GitHub Token não fornecido. Gere um token com o escopo "gist".');
|
|
1930
|
-
const e = t.trim(),
|
|
1931
|
+
const e = t.trim(), r = `backtrack-${d.incident.id}.ffr.json`, n = `Backtrack Incident Replay [${d.incident.id}]: ${d.incident.reason}`, i = JSON.stringify(d, null, 2);
|
|
1931
1932
|
if (new TextEncoder().encode(i).length > 10 * 1024 * 1024)
|
|
1932
1933
|
throw new Error("O artefato excede o limite máximo de 10 MB suportado para upload.");
|
|
1933
1934
|
const s = {
|
|
1934
|
-
description:
|
|
1935
|
+
description: n,
|
|
1935
1936
|
public: !1,
|
|
1936
1937
|
files: {
|
|
1937
|
-
[
|
|
1938
|
+
[r]: {
|
|
1938
1939
|
content: i
|
|
1939
1940
|
}
|
|
1940
1941
|
}
|
|
@@ -1957,7 +1958,7 @@ async function bt(d, t) {
|
|
|
1957
1958
|
}
|
|
1958
1959
|
throw o.status === 401 ? new Error(`Falha de autenticação no GitHub (401). Verifique se o seu token possui o escopo 'gist': ${u}`) : o.status === 422 ? new Error(`O arquivo excede o limite suportado pelo GitHub Gist (10MB): ${u}`) : new Error(`Erro ao criar Gist no GitHub (${o.status}): ${u}`);
|
|
1959
1960
|
}
|
|
1960
|
-
const c = await o.json(), h = c.files && (c.files[
|
|
1961
|
+
const c = await o.json(), h = c.files && (c.files[r] || Object.values(c.files)[0]);
|
|
1961
1962
|
return {
|
|
1962
1963
|
gistId: c.id,
|
|
1963
1964
|
gistUrl: c.html_url,
|
|
@@ -2003,17 +2004,17 @@ class ie {
|
|
|
2003
2004
|
user-select: none;
|
|
2004
2005
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
2005
2006
|
`;
|
|
2006
|
-
const
|
|
2007
|
-
|
|
2007
|
+
const r = document.createElement("canvas");
|
|
2008
|
+
r.className = "backtrack-ignore backtrack-block rr-ignore rr-block", r.setAttribute("data-rr-ignore", "true"), r.setAttribute("data-backtrack-ignore", "true"), r.width = window.innerWidth, r.height = window.innerHeight, r.style.cssText = `
|
|
2008
2009
|
position: absolute;
|
|
2009
2010
|
top: 0;
|
|
2010
2011
|
left: 0;
|
|
2011
2012
|
width: 100%;
|
|
2012
2013
|
height: 100%;
|
|
2013
2014
|
touch-action: none;
|
|
2014
|
-
`, e.appendChild(
|
|
2015
|
-
const
|
|
2016
|
-
|
|
2015
|
+
`, e.appendChild(r);
|
|
2016
|
+
const n = document.createElement("style");
|
|
2017
|
+
n.textContent = `
|
|
2017
2018
|
.backtrack-annotator-toolbar {
|
|
2018
2019
|
position: fixed;
|
|
2019
2020
|
top: 18px;
|
|
@@ -2060,9 +2061,9 @@ class ie {
|
|
|
2060
2061
|
flex-shrink: 0 !important;
|
|
2061
2062
|
}
|
|
2062
2063
|
}
|
|
2063
|
-
`, e.appendChild(
|
|
2064
|
-
const i =
|
|
2065
|
-
this.ctx = i, this.canvas =
|
|
2064
|
+
`, e.appendChild(n);
|
|
2065
|
+
const i = r.getContext ? r.getContext("2d") : null;
|
|
2066
|
+
this.ctx = i, this.canvas = r, this.overlay = e;
|
|
2066
2067
|
const a = document.createElement("div");
|
|
2067
2068
|
a.className = "backtrack-ignore backtrack-block rr-ignore rr-block backtrack-annotator-toolbar", a.setAttribute("data-rr-ignore", "true"), a.setAttribute("data-backtrack-ignore", "true"), a.innerHTML = `
|
|
2068
2069
|
<!-- Mover / Selecionar (V) -->
|
|
@@ -2187,13 +2188,13 @@ class ie {
|
|
|
2187
2188
|
h === "v" ? this.selectTool("select", a) : h === "p" ? this.selectTool("pen", a) : h === "a" ? this.selectTool("arrow", a) : h === "r" ? this.selectTool("rect", a) : h === "m" ? this.selectTool("ruler", a) : h === "t" && this.selectTool("text", a);
|
|
2188
2189
|
}
|
|
2189
2190
|
};
|
|
2190
|
-
window.addEventListener("keydown", s),
|
|
2191
|
+
window.addEventListener("keydown", s), r.addEventListener("mousedown", (o) => {
|
|
2191
2192
|
this.handlePointerDown(o.clientX, o.clientY);
|
|
2192
|
-
}),
|
|
2193
|
+
}), r.addEventListener("mousemove", (o) => {
|
|
2193
2194
|
this.handlePointerMove(o.clientX, o.clientY, !0);
|
|
2194
|
-
}),
|
|
2195
|
+
}), r.addEventListener("mouseup", (o) => {
|
|
2195
2196
|
this.handlePointerUp(o.clientX, o.clientY);
|
|
2196
|
-
}),
|
|
2197
|
+
}), r.addEventListener(
|
|
2197
2198
|
"touchstart",
|
|
2198
2199
|
(o) => {
|
|
2199
2200
|
if (o.touches.length > 0) {
|
|
@@ -2203,7 +2204,7 @@ class ie {
|
|
|
2203
2204
|
}
|
|
2204
2205
|
},
|
|
2205
2206
|
{ passive: !1 }
|
|
2206
|
-
),
|
|
2207
|
+
), r.addEventListener(
|
|
2207
2208
|
"touchmove",
|
|
2208
2209
|
(o) => {
|
|
2209
2210
|
if (o.touches.length > 0) {
|
|
@@ -2213,7 +2214,7 @@ class ie {
|
|
|
2213
2214
|
}
|
|
2214
2215
|
},
|
|
2215
2216
|
{ passive: !1 }
|
|
2216
|
-
),
|
|
2217
|
+
), r.addEventListener(
|
|
2217
2218
|
"touchend",
|
|
2218
2219
|
(o) => {
|
|
2219
2220
|
o.preventDefault();
|
|
@@ -2225,10 +2226,10 @@ class ie {
|
|
|
2225
2226
|
}
|
|
2226
2227
|
handlePointerDown(t, e) {
|
|
2227
2228
|
this.closePopover();
|
|
2228
|
-
const
|
|
2229
|
-
if (this.tool === "select" ||
|
|
2230
|
-
if (
|
|
2231
|
-
this.selectedItemId =
|
|
2229
|
+
const r = this.findItemAt(t, e);
|
|
2230
|
+
if (this.tool === "select" || r && this.tool !== "pen") {
|
|
2231
|
+
if (r) {
|
|
2232
|
+
this.selectedItemId = r.id, this.isDraggingItem = !0, this.dragStartX = t, this.dragStartY = e, this.canvas && (this.canvas.style.cursor = "grabbing"), this.redraw();
|
|
2232
2233
|
return;
|
|
2233
2234
|
}
|
|
2234
2235
|
if (this.selectedItemId = null, this.redraw(), this.tool === "select") return;
|
|
@@ -2239,12 +2240,12 @@ class ie {
|
|
|
2239
2240
|
}
|
|
2240
2241
|
this.isMouseDown = !0, this.activeDrawStart = { x: t, y: e }, this.dragStartX = t, this.dragStartY = e, this.tool === "pen" && (this.activePoints = [{ x: t, y: e }]);
|
|
2241
2242
|
}
|
|
2242
|
-
handlePointerMove(t, e,
|
|
2243
|
+
handlePointerMove(t, e, r) {
|
|
2243
2244
|
if (this.isDraggingItem && this.selectedItemId) {
|
|
2244
|
-
const
|
|
2245
|
-
if (
|
|
2245
|
+
const n = this.items.find((i) => i.id === this.selectedItemId);
|
|
2246
|
+
if (n) {
|
|
2246
2247
|
const i = t - this.dragStartX, a = e - this.dragStartY;
|
|
2247
|
-
this.dragStartX = t, this.dragStartY = e,
|
|
2248
|
+
this.dragStartX = t, this.dragStartY = e, n.x1 += i, n.y1 += a, n.x2 += i, n.y2 += a, n.points && n.points.forEach((s) => {
|
|
2248
2249
|
s.x += i, s.y += a;
|
|
2249
2250
|
}), this.redraw();
|
|
2250
2251
|
return;
|
|
@@ -2254,13 +2255,13 @@ class ie {
|
|
|
2254
2255
|
this.tool === "pen" ? (this.activePoints.push({ x: t, y: e }), this.redraw(), this.drawLivePen(this.activePoints, this.color)) : this.tool === "rect" ? (this.redraw(), this.drawLiveRect(this.activeDrawStart.x, this.activeDrawStart.y, t, e, this.color)) : this.tool === "arrow" ? (this.redraw(), this.drawLiveArrow(this.activeDrawStart.x, this.activeDrawStart.y, t, e, this.color)) : this.tool === "ruler" && (this.redraw(), this.drawLiveRuler(this.activeDrawStart.x, this.activeDrawStart.y, t, e, this.color));
|
|
2255
2256
|
return;
|
|
2256
2257
|
}
|
|
2257
|
-
if (
|
|
2258
|
+
if (r && this.canvas)
|
|
2258
2259
|
if (this.tool === "select") {
|
|
2259
|
-
const
|
|
2260
|
-
this.canvas.style.cursor =
|
|
2260
|
+
const n = this.findItemAt(t, e);
|
|
2261
|
+
this.canvas.style.cursor = n ? "grab" : "default";
|
|
2261
2262
|
} else {
|
|
2262
|
-
const
|
|
2263
|
-
this.canvas.style.cursor =
|
|
2263
|
+
const n = this.findItemAt(t, e);
|
|
2264
|
+
this.canvas.style.cursor = n ? "grab" : "crosshair";
|
|
2264
2265
|
}
|
|
2265
2266
|
}
|
|
2266
2267
|
handlePointerUp(t, e) {
|
|
@@ -2270,15 +2271,15 @@ class ie {
|
|
|
2270
2271
|
}
|
|
2271
2272
|
if (!this.isMouseDown) return;
|
|
2272
2273
|
this.isMouseDown = !1;
|
|
2273
|
-
const
|
|
2274
|
+
const r = this.activeDrawStart.x, n = this.activeDrawStart.y;
|
|
2274
2275
|
if (this.tool === "pen") {
|
|
2275
2276
|
if (this.activePoints.length > 1) {
|
|
2276
2277
|
const i = {
|
|
2277
2278
|
id: `item_${Date.now()}_${Math.random()}`,
|
|
2278
2279
|
type: "pen",
|
|
2279
2280
|
color: this.color,
|
|
2280
|
-
x1:
|
|
2281
|
-
y1:
|
|
2281
|
+
x1: r,
|
|
2282
|
+
y1: n,
|
|
2282
2283
|
x2: t,
|
|
2283
2284
|
y2: e,
|
|
2284
2285
|
points: [...this.activePoints]
|
|
@@ -2287,13 +2288,13 @@ class ie {
|
|
|
2287
2288
|
}
|
|
2288
2289
|
this.activePoints = [], this.redraw();
|
|
2289
2290
|
} else if (this.tool === "rect") {
|
|
2290
|
-
if (Math.hypot(t -
|
|
2291
|
+
if (Math.hypot(t - r, e - n) >= 4) {
|
|
2291
2292
|
const i = {
|
|
2292
2293
|
id: `item_${Date.now()}_${Math.random()}`,
|
|
2293
2294
|
type: "rect",
|
|
2294
2295
|
color: this.color,
|
|
2295
|
-
x1:
|
|
2296
|
-
y1:
|
|
2296
|
+
x1: r,
|
|
2297
|
+
y1: n,
|
|
2297
2298
|
x2: t,
|
|
2298
2299
|
y2: e
|
|
2299
2300
|
};
|
|
@@ -2301,13 +2302,13 @@ class ie {
|
|
|
2301
2302
|
}
|
|
2302
2303
|
this.redraw();
|
|
2303
2304
|
} else if (this.tool === "arrow") {
|
|
2304
|
-
if (Math.hypot(t -
|
|
2305
|
+
if (Math.hypot(t - r, e - n) >= 6) {
|
|
2305
2306
|
const i = {
|
|
2306
2307
|
id: `item_${Date.now()}_${Math.random()}`,
|
|
2307
2308
|
type: "arrow",
|
|
2308
2309
|
color: this.color,
|
|
2309
|
-
x1:
|
|
2310
|
-
y1:
|
|
2310
|
+
x1: r,
|
|
2311
|
+
y1: n,
|
|
2311
2312
|
x2: t,
|
|
2312
2313
|
y2: e
|
|
2313
2314
|
};
|
|
@@ -2315,11 +2316,11 @@ class ie {
|
|
|
2315
2316
|
}
|
|
2316
2317
|
this.redraw();
|
|
2317
2318
|
} else if (this.tool === "ruler") {
|
|
2318
|
-
if (Math.hypot(t -
|
|
2319
|
+
if (Math.hypot(t - r, e - n) < 4) {
|
|
2319
2320
|
this.redraw();
|
|
2320
2321
|
return;
|
|
2321
2322
|
}
|
|
2322
|
-
const i = t -
|
|
2323
|
+
const i = t - r, a = e - n, s = Math.round(Math.abs(i)), o = Math.round(Math.abs(a));
|
|
2323
2324
|
let c = "", h = "";
|
|
2324
2325
|
if (o >= s) {
|
|
2325
2326
|
const p = a >= 0 ? "bottom" : "top";
|
|
@@ -2332,8 +2333,8 @@ class ie {
|
|
|
2332
2333
|
id: `item_${Date.now()}_${Math.random()}`,
|
|
2333
2334
|
type: "ruler",
|
|
2334
2335
|
color: this.color,
|
|
2335
|
-
x1:
|
|
2336
|
-
y1:
|
|
2336
|
+
x1: r,
|
|
2337
|
+
y1: n,
|
|
2337
2338
|
x2: t,
|
|
2338
2339
|
y2: e,
|
|
2339
2340
|
note: c,
|
|
@@ -2355,24 +2356,24 @@ class ie {
|
|
|
2355
2356
|
return "width: 33px; height: 33px; border-radius: 7px; display: flex; align-items: center; justify-content: center; border: 1px solid #334155; background: #1e293b; color: #cbd5e1; cursor: pointer; padding: 0; transition: background 0.15s ease;";
|
|
2356
2357
|
}
|
|
2357
2358
|
selectTool(t, e) {
|
|
2358
|
-
this.tool = t, ["select", "pen", "arrow", "rect", "ruler", "text"].forEach((
|
|
2359
|
-
const i = e.querySelector(`#btn-tool-${
|
|
2359
|
+
this.tool = t, ["select", "pen", "arrow", "rect", "ruler", "text"].forEach((n) => {
|
|
2360
|
+
const i = e.querySelector(`#btn-tool-${n}`);
|
|
2360
2361
|
if (i) {
|
|
2361
|
-
const a =
|
|
2362
|
+
const a = n === t;
|
|
2362
2363
|
i.style.background = a ? "#3b82f6" : "#1e293b", i.style.borderColor = a ? "#60a5fa" : "#334155", i.style.boxShadow = a ? "0 0 10px rgba(59, 130, 246, 0.4)" : "none";
|
|
2363
2364
|
}
|
|
2364
2365
|
}), this.canvas && (this.canvas.style.cursor = t === "select" ? "default" : "crosshair");
|
|
2365
2366
|
}
|
|
2366
2367
|
setupToolbarEvents(t) {
|
|
2367
|
-
var
|
|
2368
|
+
var n, i, a, s;
|
|
2368
2369
|
["select", "pen", "arrow", "rect", "ruler", "text"].forEach((o) => {
|
|
2369
2370
|
const c = t.querySelector(`#btn-tool-${o}`);
|
|
2370
2371
|
c == null || c.addEventListener("click", (h) => {
|
|
2371
2372
|
h.stopPropagation(), this.selectTool(o, t);
|
|
2372
2373
|
});
|
|
2373
2374
|
});
|
|
2374
|
-
const
|
|
2375
|
-
|
|
2375
|
+
const r = t.querySelectorAll(".backtrack-color-btn");
|
|
2376
|
+
r.forEach((o) => {
|
|
2376
2377
|
o.addEventListener("click", (c) => {
|
|
2377
2378
|
c.stopPropagation();
|
|
2378
2379
|
const h = o.getAttribute("data-color") || "#ef4444";
|
|
@@ -2380,11 +2381,11 @@ class ie {
|
|
|
2380
2381
|
const u = this.items.find((p) => p.id === this.selectedItemId);
|
|
2381
2382
|
u && (u.color = h, this.redraw(), this.recordHistory());
|
|
2382
2383
|
}
|
|
2383
|
-
|
|
2384
|
+
r.forEach((u) => {
|
|
2384
2385
|
u.style.boxShadow = "none", u.style.opacity = "0.75";
|
|
2385
2386
|
}), o.style.boxShadow = "0 0 0 2px #fff", o.style.opacity = "1";
|
|
2386
2387
|
});
|
|
2387
|
-
}), (
|
|
2388
|
+
}), (n = t.querySelector("#btn-undo")) == null || n.addEventListener("click", (o) => {
|
|
2388
2389
|
o.stopPropagation(), this.undo();
|
|
2389
2390
|
}), (i = t.querySelector("#btn-clear")) == null || i.addEventListener("click", (o) => {
|
|
2390
2391
|
o.stopPropagation(), this.clear();
|
|
@@ -2405,13 +2406,13 @@ class ie {
|
|
|
2405
2406
|
} catch {
|
|
2406
2407
|
}
|
|
2407
2408
|
const e = [];
|
|
2408
|
-
this.items.forEach((
|
|
2409
|
-
|
|
2409
|
+
this.items.forEach((n) => {
|
|
2410
|
+
n.note && n.note.trim() ? e.push(n.note.trim()) : n.text && n.text.trim() && e.push(n.text.trim());
|
|
2410
2411
|
});
|
|
2411
|
-
const
|
|
2412
|
+
const r = e.length > 0 ? e.join(" | ") : "Anotação visual de bug na tela";
|
|
2412
2413
|
this.close(), this.onComplete && this.onComplete({
|
|
2413
2414
|
dataUrl: t,
|
|
2414
|
-
notes:
|
|
2415
|
+
notes: r
|
|
2415
2416
|
});
|
|
2416
2417
|
}
|
|
2417
2418
|
/**
|
|
@@ -2421,42 +2422,42 @@ class ie {
|
|
|
2421
2422
|
if (!this.ctx || !this.canvas) return;
|
|
2422
2423
|
const t = this.ctx;
|
|
2423
2424
|
t.clearRect(0, 0, this.canvas.width, this.canvas.height), this.items.forEach((e) => {
|
|
2424
|
-
const
|
|
2425
|
+
const r = e.id === this.selectedItemId;
|
|
2425
2426
|
if (e.type === "pen" && e.points)
|
|
2426
|
-
t.strokeStyle = e.color, t.lineWidth = 3, t.lineCap = "round", t.lineJoin = "round", t.beginPath(), e.points.forEach((
|
|
2427
|
-
i === 0 ? t.moveTo(
|
|
2427
|
+
t.strokeStyle = e.color, t.lineWidth = 3, t.lineCap = "round", t.lineJoin = "round", t.beginPath(), e.points.forEach((n, i) => {
|
|
2428
|
+
i === 0 ? t.moveTo(n.x, n.y) : t.lineTo(n.x, n.y);
|
|
2428
2429
|
}), t.stroke();
|
|
2429
2430
|
else if (e.type === "rect") {
|
|
2430
|
-
const
|
|
2431
|
-
t.strokeStyle = e.color, t.lineWidth = 3, t.strokeRect(
|
|
2431
|
+
const n = Math.min(e.x1, e.x2), i = Math.min(e.y1, e.y2), a = Math.abs(e.x2 - e.x1), s = Math.abs(e.y2 - e.y1);
|
|
2432
|
+
t.strokeStyle = e.color, t.lineWidth = 3, t.strokeRect(n, i, a, s);
|
|
2432
2433
|
} else e.type === "arrow" ? this.drawLiveArrow(e.x1, e.y1, e.x2, e.y2, e.color) : e.type === "ruler" ? this.renderTechnicalRuler(e.x1, e.y1, e.x2, e.y2, e.color, e.label || "0px") : e.type === "text" && e.text && this.renderTextItem(e.x1, e.y1, e.text, e.color);
|
|
2433
|
-
|
|
2434
|
+
r && this.drawSelectionOutline(e);
|
|
2434
2435
|
});
|
|
2435
2436
|
}
|
|
2436
2437
|
drawLivePen(t, e) {
|
|
2437
|
-
!this.ctx || t.length < 2 || (this.ctx.strokeStyle = e, this.ctx.lineWidth = 3, this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.beginPath(), t.forEach((
|
|
2438
|
-
|
|
2438
|
+
!this.ctx || t.length < 2 || (this.ctx.strokeStyle = e, this.ctx.lineWidth = 3, this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.beginPath(), t.forEach((r, n) => {
|
|
2439
|
+
n === 0 ? this.ctx.moveTo(r.x, r.y) : this.ctx.lineTo(r.x, r.y);
|
|
2439
2440
|
}), this.ctx.stroke());
|
|
2440
2441
|
}
|
|
2441
|
-
drawLiveRect(t, e,
|
|
2442
|
+
drawLiveRect(t, e, r, n, i) {
|
|
2442
2443
|
if (!this.ctx) return;
|
|
2443
|
-
const a = Math.min(t,
|
|
2444
|
+
const a = Math.min(t, r), s = Math.min(e, n), o = Math.abs(r - t), c = Math.abs(n - e);
|
|
2444
2445
|
this.ctx.strokeStyle = i, this.ctx.lineWidth = 3, this.ctx.strokeRect(a, s, o, c);
|
|
2445
2446
|
}
|
|
2446
|
-
drawLiveArrow(t, e,
|
|
2447
|
+
drawLiveArrow(t, e, r, n, i) {
|
|
2447
2448
|
if (!this.ctx) return;
|
|
2448
|
-
const a = 14, s = Math.atan2(
|
|
2449
|
-
this.ctx.strokeStyle = i, this.ctx.fillStyle = i, this.ctx.lineWidth = 3, this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.beginPath(), this.ctx.moveTo(t, e), this.ctx.lineTo(
|
|
2450
|
-
|
|
2451
|
-
|
|
2449
|
+
const a = 14, s = Math.atan2(n - e, r - t);
|
|
2450
|
+
this.ctx.strokeStyle = i, this.ctx.fillStyle = i, this.ctx.lineWidth = 3, this.ctx.lineCap = "round", this.ctx.lineJoin = "round", this.ctx.beginPath(), this.ctx.moveTo(t, e), this.ctx.lineTo(r, n), this.ctx.stroke(), this.ctx.beginPath(), this.ctx.moveTo(r, n), this.ctx.lineTo(
|
|
2451
|
+
r - a * Math.cos(s - Math.PI / 6),
|
|
2452
|
+
n - a * Math.sin(s - Math.PI / 6)
|
|
2452
2453
|
), this.ctx.lineTo(
|
|
2453
|
-
|
|
2454
|
-
|
|
2454
|
+
r - a * Math.cos(s + Math.PI / 6),
|
|
2455
|
+
n - a * Math.sin(s + Math.PI / 6)
|
|
2455
2456
|
), this.ctx.closePath(), this.ctx.fill();
|
|
2456
2457
|
}
|
|
2457
|
-
drawLiveRuler(t, e,
|
|
2458
|
+
drawLiveRuler(t, e, r, n, i) {
|
|
2458
2459
|
if (!this.ctx) return;
|
|
2459
|
-
const a =
|
|
2460
|
+
const a = r - t, s = n - e, o = Math.round(Math.abs(a)), c = Math.round(Math.abs(s));
|
|
2460
2461
|
let h = "";
|
|
2461
2462
|
if (c >= o) {
|
|
2462
2463
|
const u = s >= 0 ? "bottom" : "top";
|
|
@@ -2465,34 +2466,34 @@ class ie {
|
|
|
2465
2466
|
const u = a >= 0 ? "right" : "left";
|
|
2466
2467
|
h = `${o}px ${a >= 0 ? "→" : "←"} ${u}`;
|
|
2467
2468
|
}
|
|
2468
|
-
this.renderTechnicalRuler(t, e,
|
|
2469
|
+
this.renderTechnicalRuler(t, e, r, n, i, h);
|
|
2469
2470
|
}
|
|
2470
2471
|
/**
|
|
2471
2472
|
* Renderiza cota técnica com o badge DESLOCADO por 18px perpendicularmente à linha,
|
|
2472
2473
|
* para NUNCA encobrir ou obstruir a seta / linha de medição!
|
|
2473
2474
|
*/
|
|
2474
|
-
renderTechnicalRuler(t, e,
|
|
2475
|
+
renderTechnicalRuler(t, e, r, n, i, a) {
|
|
2475
2476
|
if (!this.ctx) return;
|
|
2476
|
-
const s = this.ctx, c = Math.atan2(
|
|
2477
|
-
s.save(), s.strokeStyle = i, s.lineWidth = 2, s.lineCap = "butt", s.beginPath(), s.moveTo(t, e), s.lineTo(
|
|
2477
|
+
const s = this.ctx, c = Math.atan2(n - e, r - t) + Math.PI / 2, h = 9;
|
|
2478
|
+
s.save(), s.strokeStyle = i, s.lineWidth = 2, s.lineCap = "butt", s.beginPath(), s.moveTo(t, e), s.lineTo(r, n), s.stroke();
|
|
2478
2479
|
const u = (M, A) => {
|
|
2479
2480
|
s.beginPath(), s.moveTo(M - h * Math.cos(c), A - h * Math.sin(c)), s.lineTo(M + h * Math.cos(c), A + h * Math.sin(c)), s.stroke();
|
|
2480
2481
|
};
|
|
2481
|
-
u(t, e), u(
|
|
2482
|
-
const p = (t +
|
|
2483
|
-
let m = p, k =
|
|
2484
|
-
Math.abs(
|
|
2482
|
+
u(t, e), u(r, n);
|
|
2483
|
+
const p = (t + r) / 2, g = (e + n) / 2, b = r - t, f = n - e;
|
|
2484
|
+
let m = p, k = g;
|
|
2485
|
+
Math.abs(b) >= Math.abs(f) ? k = g - 18 : m = p + 26, s.font = 'bold 11px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2485
2486
|
const w = s.measureText(a).width + 7 * 2, E = 20;
|
|
2486
2487
|
s.fillStyle = "#0f172a", s.strokeStyle = i, s.lineWidth = 1.4;
|
|
2487
2488
|
const S = m - w / 2, C = k - E / 2;
|
|
2488
2489
|
this.roundRect(s, S, C, w, E, 4), s.fill(), s.stroke(), s.fillStyle = "#ffffff", s.textAlign = "center", s.textBaseline = "middle", s.fillText(a, m, k), s.restore();
|
|
2489
2490
|
}
|
|
2490
|
-
renderTextItem(t, e,
|
|
2491
|
+
renderTextItem(t, e, r, n) {
|
|
2491
2492
|
if (!this.ctx) return;
|
|
2492
2493
|
const i = this.ctx;
|
|
2493
2494
|
i.save(), i.font = 'bold 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
|
|
2494
|
-
const a = i.measureText(
|
|
2495
|
-
i.fillStyle = "#0f172a", i.strokeStyle =
|
|
2495
|
+
const a = i.measureText(r), s = 10, o = a.width + s * 2, c = 26;
|
|
2496
|
+
i.fillStyle = "#0f172a", i.strokeStyle = n, i.lineWidth = 1.5, this.roundRect(i, t, e, o, c, 5), i.fill(), i.stroke(), i.fillStyle = "#ffffff", i.textAlign = "left", i.textBaseline = "middle", i.fillText(r, t + s, e + c / 2), i.restore();
|
|
2496
2497
|
}
|
|
2497
2498
|
/**
|
|
2498
2499
|
* Desenha moldura sutil de seleção para indicar que o elemento pode ser arrastado
|
|
@@ -2501,22 +2502,22 @@ class ie {
|
|
|
2501
2502
|
if (!this.ctx) return;
|
|
2502
2503
|
const e = this.ctx;
|
|
2503
2504
|
e.save(), e.strokeStyle = "#38bdf8", e.lineWidth = 1.5, e.setLineDash([4, 4]);
|
|
2504
|
-
const
|
|
2505
|
+
const r = 6;
|
|
2505
2506
|
if (t.type === "rect") {
|
|
2506
|
-
const
|
|
2507
|
-
e.strokeRect(
|
|
2507
|
+
const n = Math.min(t.x1, t.x2) - r, i = Math.min(t.y1, t.y2) - r, a = Math.abs(t.x2 - t.x1) + r * 2, s = Math.abs(t.y2 - t.y1) + r * 2;
|
|
2508
|
+
e.strokeRect(n, i, a, s);
|
|
2508
2509
|
} else if (t.type === "arrow" || t.type === "ruler") {
|
|
2509
|
-
const
|
|
2510
|
-
e.strokeRect(
|
|
2510
|
+
const n = Math.min(t.x1, t.x2) - r, i = Math.min(t.y1, t.y2) - r - 20, a = Math.max(t.x1, t.x2) + r + 25, s = Math.max(t.y1, t.y2) + r;
|
|
2511
|
+
e.strokeRect(n, i, a - n, s - i);
|
|
2511
2512
|
} else if (t.type === "text") {
|
|
2512
2513
|
e.font = "bold 13px sans-serif";
|
|
2513
|
-
const
|
|
2514
|
-
e.strokeRect(t.x1 -
|
|
2514
|
+
const n = e.measureText(t.text || "").width + 20 + r * 2;
|
|
2515
|
+
e.strokeRect(t.x1 - r, t.y1 - r, n, 26 + r * 2);
|
|
2515
2516
|
} else if (t.type === "pen" && t.points) {
|
|
2516
|
-
let
|
|
2517
|
+
let n = 1 / 0, i = 1 / 0, a = -1 / 0, s = -1 / 0;
|
|
2517
2518
|
t.points.forEach((o) => {
|
|
2518
|
-
o.x <
|
|
2519
|
-
}), e.strokeRect(
|
|
2519
|
+
o.x < n && (n = o.x), o.y < i && (i = o.y), o.x > a && (a = o.x), o.y > s && (s = o.y);
|
|
2520
|
+
}), e.strokeRect(n - r, i - r, a - n + r * 2, s - i + r * 2);
|
|
2520
2521
|
}
|
|
2521
2522
|
e.restore();
|
|
2522
2523
|
}
|
|
@@ -2524,16 +2525,16 @@ class ie {
|
|
|
2524
2525
|
* Encontra qual elemento está na coordenada (x, y)
|
|
2525
2526
|
*/
|
|
2526
2527
|
findItemAt(t, e) {
|
|
2527
|
-
var
|
|
2528
|
-
for (let
|
|
2529
|
-
const i = this.items[
|
|
2528
|
+
var r;
|
|
2529
|
+
for (let n = this.items.length - 1; n >= 0; n--) {
|
|
2530
|
+
const i = this.items[n];
|
|
2530
2531
|
if (i.type === "rect") {
|
|
2531
2532
|
const a = Math.min(i.x1, i.x2) - 8, s = Math.max(i.x1, i.x2) + 8, o = Math.min(i.y1, i.y2) - 8, c = Math.max(i.y1, i.y2) + 8;
|
|
2532
2533
|
if (t >= a && t <= s && e >= o && e <= c) return i;
|
|
2533
2534
|
} else if (i.type === "arrow" || i.type === "ruler") {
|
|
2534
2535
|
if (this.distToSegment(t, e, i.x1, i.y1, i.x2, i.y2) <= 18) return i;
|
|
2535
2536
|
} else if (i.type === "text") {
|
|
2536
|
-
const a = (((
|
|
2537
|
+
const a = (((r = i.text) == null ? void 0 : r.length) || 10) * 9 + 20;
|
|
2537
2538
|
if (t >= i.x1 - 6 && t <= i.x1 + a && e >= i.y1 - 6 && e <= i.y1 + 30)
|
|
2538
2539
|
return i;
|
|
2539
2540
|
} else if (i.type === "pen" && i.points) {
|
|
@@ -2543,11 +2544,11 @@ class ie {
|
|
|
2543
2544
|
}
|
|
2544
2545
|
return null;
|
|
2545
2546
|
}
|
|
2546
|
-
distToSegment(t, e,
|
|
2547
|
-
const s = (i -
|
|
2548
|
-
if (s === 0) return Math.hypot(t -
|
|
2549
|
-
let o = ((t -
|
|
2550
|
-
return o = Math.max(0, Math.min(1, o)), Math.hypot(t - (
|
|
2547
|
+
distToSegment(t, e, r, n, i, a) {
|
|
2548
|
+
const s = (i - r) ** 2 + (a - n) ** 2;
|
|
2549
|
+
if (s === 0) return Math.hypot(t - r, e - n);
|
|
2550
|
+
let o = ((t - r) * (i - r) + (e - n) * (a - n)) / s;
|
|
2551
|
+
return o = Math.max(0, Math.min(1, o)), Math.hypot(t - (r + o * (i - r)), e - (n + o * (a - n)));
|
|
2551
2552
|
}
|
|
2552
2553
|
/**
|
|
2553
2554
|
* Popover de confirmação/edição da régua posicionado de forma limpa SEM encobrir a régua
|
|
@@ -2555,11 +2556,11 @@ class ie {
|
|
|
2555
2556
|
openRulerConfirmPopover(t) {
|
|
2556
2557
|
if (!this.overlay) return;
|
|
2557
2558
|
this.closePopover();
|
|
2558
|
-
const e = (t.x1 + t.x2) / 2,
|
|
2559
|
-
|
|
2559
|
+
const e = (t.x1 + t.x2) / 2, r = (t.y1 + t.y2) / 2, n = document.createElement("div");
|
|
2560
|
+
n.className = "backtrack-ignore backtrack-block rr-ignore rr-block", n.setAttribute("data-rr-ignore", "true"), n.setAttribute("data-backtrack-ignore", "true"), n.style.cssText = `
|
|
2560
2561
|
position: fixed;
|
|
2561
2562
|
left: ${Math.max(10, Math.min(window.innerWidth - 280, e - 140))}px;
|
|
2562
|
-
top: ${Math.min(window.innerHeight - 80, Math.max(70,
|
|
2563
|
+
top: ${Math.min(window.innerHeight - 80, Math.max(70, r + 28))}px;
|
|
2563
2564
|
background: #0f172a;
|
|
2564
2565
|
border: 1px solid #3b82f6;
|
|
2565
2566
|
box-shadow: 0 10px 25px rgba(0,0,0,0.65);
|
|
@@ -2571,12 +2572,12 @@ class ie {
|
|
|
2571
2572
|
max-width: calc(100vw - 20px);
|
|
2572
2573
|
box-sizing: border-box;
|
|
2573
2574
|
z-index: 2147483648;
|
|
2574
|
-
`,
|
|
2575
|
+
`, n.innerHTML = `
|
|
2575
2576
|
<input type="text" id="ruler-note-input" value="${t.note || ""}" style="background: #1e293b; color: #fff; border: 1px solid #334155; border-radius: 4px; padding: 4px 8px; font-size: 12px; width: 100%; max-width: 210px; min-width: 140px; outline: none; box-sizing: border-box;" />
|
|
2576
2577
|
<button type="button" id="btn-ruler-confirm" style="background: #10b981; color: white; border: none; border-radius: 4px; padding: 4px 8px; font-size: 12px; font-weight: bold; cursor: pointer; flex-shrink: 0;">✓</button>
|
|
2577
2578
|
<button type="button" id="btn-ruler-cancel" style="background: transparent; color: #94a3b8; border: none; padding: 4px; font-size: 12px; cursor: pointer; flex-shrink: 0;">✕</button>
|
|
2578
|
-
`, this.overlay.appendChild(
|
|
2579
|
-
const i =
|
|
2579
|
+
`, this.overlay.appendChild(n), this.activePopover = n;
|
|
2580
|
+
const i = n.querySelector("#ruler-note-input"), a = n.querySelector("#btn-ruler-confirm"), s = n.querySelector("#btn-ruler-cancel");
|
|
2580
2581
|
setTimeout(() => {
|
|
2581
2582
|
i == null || i.focus(), i == null || i.select();
|
|
2582
2583
|
}, 50);
|
|
@@ -2595,8 +2596,8 @@ class ie {
|
|
|
2595
2596
|
openTextInput(t, e) {
|
|
2596
2597
|
if (!this.overlay) return;
|
|
2597
2598
|
this.closePopover();
|
|
2598
|
-
const
|
|
2599
|
-
|
|
2599
|
+
const r = document.createElement("div");
|
|
2600
|
+
r.className = "backtrack-ignore backtrack-block rr-ignore rr-block", r.setAttribute("data-rr-ignore", "true"), r.setAttribute("data-backtrack-ignore", "true"), r.style.cssText = `
|
|
2600
2601
|
position: fixed;
|
|
2601
2602
|
left: ${Math.max(10, Math.min(window.innerWidth - 240, t))}px;
|
|
2602
2603
|
top: ${Math.min(window.innerHeight - 60, Math.max(60, e))}px;
|
|
@@ -2611,15 +2612,15 @@ class ie {
|
|
|
2611
2612
|
max-width: calc(100vw - 20px);
|
|
2612
2613
|
box-sizing: border-box;
|
|
2613
2614
|
z-index: 2147483648;
|
|
2614
|
-
`,
|
|
2615
|
+
`, r.innerHTML = `
|
|
2615
2616
|
<input type="text" id="canvas-text-input" placeholder="Digite a anotação..." style="background: #1e293b; color: #fff; border: 1px solid #334155; border-radius: 4px; padding: 4px 8px; font-size: 12px; width: 100%; max-width: 180px; min-width: 120px; outline: none; box-sizing: border-box;" />
|
|
2616
2617
|
<button type="button" id="btn-text-confirm" style="background: #10b981; color: white; border: none; border-radius: 4px; padding: 4px 8px; font-size: 12px; font-weight: bold; cursor: pointer; flex-shrink: 0;">✓</button>
|
|
2617
2618
|
<button type="button" id="btn-text-cancel" style="background: transparent; color: #94a3b8; border: none; padding: 4px; font-size: 12px; cursor: pointer; flex-shrink: 0;">✕</button>
|
|
2618
|
-
`, this.overlay.appendChild(
|
|
2619
|
-
const
|
|
2620
|
-
setTimeout(() =>
|
|
2619
|
+
`, this.overlay.appendChild(r), this.activePopover = r;
|
|
2620
|
+
const n = r.querySelector("#canvas-text-input"), i = r.querySelector("#btn-text-confirm"), a = r.querySelector("#btn-text-cancel");
|
|
2621
|
+
setTimeout(() => n == null ? void 0 : n.focus(), 50);
|
|
2621
2622
|
const s = () => {
|
|
2622
|
-
const o =
|
|
2623
|
+
const o = n.value.trim();
|
|
2623
2624
|
if (this.closePopover(), !o) return;
|
|
2624
2625
|
const c = {
|
|
2625
2626
|
id: `item_${Date.now()}_${Math.random()}`,
|
|
@@ -2635,7 +2636,7 @@ class ie {
|
|
|
2635
2636
|
};
|
|
2636
2637
|
i.addEventListener("click", (o) => {
|
|
2637
2638
|
o.stopPropagation(), s();
|
|
2638
|
-
}),
|
|
2639
|
+
}), n.addEventListener("keydown", (o) => {
|
|
2639
2640
|
o.key === "Enter" ? (o.preventDefault(), s()) : o.key === "Escape" && (o.preventDefault(), this.closePopover());
|
|
2640
2641
|
}), a.addEventListener("click", (o) => {
|
|
2641
2642
|
o.stopPropagation(), this.closePopover();
|
|
@@ -2644,8 +2645,8 @@ class ie {
|
|
|
2644
2645
|
closePopover() {
|
|
2645
2646
|
this.activePopover && this.activePopover.parentNode && this.activePopover.parentNode.removeChild(this.activePopover), this.activePopover = null;
|
|
2646
2647
|
}
|
|
2647
|
-
roundRect(t, e,
|
|
2648
|
-
t.beginPath(), t.moveTo(e + a,
|
|
2648
|
+
roundRect(t, e, r, n, i, a) {
|
|
2649
|
+
t.beginPath(), t.moveTo(e + a, r), t.lineTo(e + n - a, r), t.quadraticCurveTo(e + n, r, e + n, r + a), t.lineTo(e + n, r + i - a), t.quadraticCurveTo(e + n, r + i, e + n - a, r + i), t.lineTo(e + a, r + i), t.quadraticCurveTo(e, r + i, e, r + i - a), t.lineTo(e, r + a), t.quadraticCurveTo(e, r, e + a, r), t.closePath();
|
|
2649
2650
|
}
|
|
2650
2651
|
recordHistory() {
|
|
2651
2652
|
const t = this.items.map((e) => ({
|
|
@@ -3798,7 +3799,7 @@ const ae = `
|
|
|
3798
3799
|
white-space: nowrap;
|
|
3799
3800
|
border-width: 0;
|
|
3800
3801
|
}
|
|
3801
|
-
`,
|
|
3802
|
+
`, bt = "https://backtrack-viewer.netlify.app", $ = class $ {
|
|
3802
3803
|
constructor(t, e) {
|
|
3803
3804
|
l(this, "recorder");
|
|
3804
3805
|
l(this, "options");
|
|
@@ -3831,7 +3832,7 @@ const ae = `
|
|
|
3831
3832
|
this.recorder = t, this.options = {
|
|
3832
3833
|
position: (e == null ? void 0 : e.position) ?? "bottom-left",
|
|
3833
3834
|
zIndex: (e == null ? void 0 : e.zIndex) ?? 999999,
|
|
3834
|
-
defaultViewerUrl: (e == null ? void 0 : e.defaultViewerUrl) ??
|
|
3835
|
+
defaultViewerUrl: (e == null ? void 0 : e.defaultViewerUrl) ?? bt
|
|
3835
3836
|
};
|
|
3836
3837
|
}
|
|
3837
3838
|
mount() {
|
|
@@ -3923,7 +3924,7 @@ const ae = `
|
|
|
3923
3924
|
}
|
|
3924
3925
|
} catch {
|
|
3925
3926
|
}
|
|
3926
|
-
return (this.options.defaultViewerUrl ||
|
|
3927
|
+
return (this.options.defaultViewerUrl || bt).replace(/\/+$/, "");
|
|
3927
3928
|
}
|
|
3928
3929
|
async updateData() {
|
|
3929
3930
|
try {
|
|
@@ -3931,15 +3932,15 @@ const ae = `
|
|
|
3931
3932
|
} catch {
|
|
3932
3933
|
}
|
|
3933
3934
|
}
|
|
3934
|
-
showToast(t, e = "success",
|
|
3935
|
+
showToast(t, e = "success", r = 2800) {
|
|
3935
3936
|
var i;
|
|
3936
3937
|
this.toastTimer && (clearTimeout(this.toastTimer), this.toastTimer = null), this.toast = { message: t, type: e };
|
|
3937
|
-
const
|
|
3938
|
-
if (
|
|
3939
|
-
const a =
|
|
3938
|
+
const n = (i = this.shadow) == null ? void 0 : i.querySelector(".backtrack-panel");
|
|
3939
|
+
if (n) {
|
|
3940
|
+
const a = n.querySelector(".backtrack-toast-wrap");
|
|
3940
3941
|
a && a.remove();
|
|
3941
3942
|
const s = document.createElement("div");
|
|
3942
|
-
s.innerHTML = this.renderToastHtml(), s.firstElementChild &&
|
|
3943
|
+
s.innerHTML = this.renderToastHtml(), s.firstElementChild && n.appendChild(s.firstElementChild);
|
|
3943
3944
|
} else
|
|
3944
3945
|
this.render();
|
|
3945
3946
|
this.toastTimer = setTimeout(() => {
|
|
@@ -3947,17 +3948,17 @@ const ae = `
|
|
|
3947
3948
|
this.toast = null, this.toastTimer = null;
|
|
3948
3949
|
const a = (s = this.shadow) == null ? void 0 : s.querySelector(".backtrack-toast-wrap");
|
|
3949
3950
|
a && a.remove();
|
|
3950
|
-
},
|
|
3951
|
+
}, r);
|
|
3951
3952
|
}
|
|
3952
3953
|
showBanner(t, e = "danger") {
|
|
3953
|
-
var
|
|
3954
|
+
var n, i, a;
|
|
3954
3955
|
this.banner = { message: t, type: e };
|
|
3955
|
-
const
|
|
3956
|
-
if (
|
|
3957
|
-
const s =
|
|
3956
|
+
const r = (n = this.shadow) == null ? void 0 : n.querySelector(".backtrack-panel-body");
|
|
3957
|
+
if (r) {
|
|
3958
|
+
const s = r.querySelector(".backtrack-banner");
|
|
3958
3959
|
s && s.remove();
|
|
3959
3960
|
const o = document.createElement("div");
|
|
3960
|
-
o.innerHTML = this.renderBannerHtml(), o.firstElementChild && (
|
|
3961
|
+
o.innerHTML = this.renderBannerHtml(), o.firstElementChild && (r.insertBefore(o.firstElementChild, r.firstChild), (a = (i = this.shadow) == null ? void 0 : i.getElementById("btn-dismiss-banner")) == null || a.addEventListener("click", () => {
|
|
3961
3962
|
this.dismissBanner();
|
|
3962
3963
|
}));
|
|
3963
3964
|
} else
|
|
@@ -4017,8 +4018,8 @@ const ae = `
|
|
|
4017
4018
|
}
|
|
4018
4019
|
this.isDownloading = !0, this.downloadModalError = null, this.render();
|
|
4019
4020
|
try {
|
|
4020
|
-
const e = this.downloadModalFormat === "ai",
|
|
4021
|
-
await this.recorder.exportIncident(t, { compress:
|
|
4021
|
+
const e = this.downloadModalFormat === "ai", r = this.downloadModalFormat === "gzip";
|
|
4022
|
+
await this.recorder.exportIncident(t, { compress: r, aiOptimized: e }), this.showToast("Download iniciado.", "success");
|
|
4022
4023
|
} catch {
|
|
4023
4024
|
this.downloadModalError = "Falha ao exportar incidente.", this.isDownloading = !1, this.render();
|
|
4024
4025
|
return;
|
|
@@ -4043,7 +4044,7 @@ const ae = `
|
|
|
4043
4044
|
this.isExportingMarkdown = !0, this.exportModalError = null, this.render();
|
|
4044
4045
|
try {
|
|
4045
4046
|
const e = await this.recorder.getArtifact(t);
|
|
4046
|
-
let
|
|
4047
|
+
let r;
|
|
4047
4048
|
if (this.exportModalIncludeLink) {
|
|
4048
4049
|
const a = new TextEncoder().encode(JSON.stringify(e)).byteLength, s = 10 * 1024 * 1024;
|
|
4049
4050
|
if (a > s)
|
|
@@ -4059,31 +4060,31 @@ const ae = `
|
|
|
4059
4060
|
}
|
|
4060
4061
|
o = p.trim(), $.sessionGithubToken = o;
|
|
4061
4062
|
}
|
|
4062
|
-
const c = await
|
|
4063
|
-
|
|
4063
|
+
const c = await gt(e, o);
|
|
4064
|
+
r = `${this.getViewerUrl()}/?gist=${c.gistId}`;
|
|
4064
4065
|
const u = Math.floor(
|
|
4065
4066
|
Math.max(0, (e.incident.triggeredAt || e.incident.finalizedAt) - e.incident.startedAt) / 1e3
|
|
4066
4067
|
);
|
|
4067
|
-
|
|
4068
|
+
r && u > 0 && !r.includes("&t=") && !r.includes("?t=") && (r += (r.includes("?") ? "&" : "?") + `t=${u}`);
|
|
4068
4069
|
}
|
|
4069
|
-
const
|
|
4070
|
+
const n = St(e, { replayUrl: r });
|
|
4070
4071
|
let i = !1;
|
|
4071
4072
|
if (typeof navigator < "u" && navigator.clipboard && navigator.clipboard.writeText)
|
|
4072
4073
|
try {
|
|
4073
|
-
await navigator.clipboard.writeText(
|
|
4074
|
+
await navigator.clipboard.writeText(n), i = !0;
|
|
4074
4075
|
} catch {
|
|
4075
4076
|
}
|
|
4076
4077
|
if (!i && typeof document < "u")
|
|
4077
4078
|
try {
|
|
4078
4079
|
const a = document.createElement("textarea");
|
|
4079
|
-
a.value =
|
|
4080
|
+
a.value = n, a.style.position = "fixed", a.style.opacity = "0", document.body.appendChild(a), a.focus(), a.select(), i = document.execCommand("copy"), document.body.removeChild(a);
|
|
4080
4081
|
} catch {
|
|
4081
4082
|
i = !1;
|
|
4082
4083
|
}
|
|
4083
4084
|
i ? this.showToast(this.exportModalIncludeLink ? "Link copiado." : "Markdown copiado.", "success") : this.showToast("Área de transferência indisponível.", "danger");
|
|
4084
4085
|
} catch (e) {
|
|
4085
|
-
const
|
|
4086
|
-
|
|
4086
|
+
const r = e instanceof Error ? e.message : String(e);
|
|
4087
|
+
r.includes("401") && ($.sessionGithubToken = null), this.exportModalError = `Falha: ${r}`, this.isExportingMarkdown = !1, this.render();
|
|
4087
4088
|
return;
|
|
4088
4089
|
} finally {
|
|
4089
4090
|
this.isExportingMarkdown = !1;
|
|
@@ -4094,16 +4095,16 @@ const ae = `
|
|
|
4094
4095
|
async handleShareGist(t) {
|
|
4095
4096
|
let e = $.sessionGithubToken;
|
|
4096
4097
|
if (!e || !e.trim()) {
|
|
4097
|
-
const
|
|
4098
|
+
const r = prompt(
|
|
4098
4099
|
`Insira seu GitHub Personal Access Token (com permissão "gist") para gerar o link não listado:
|
|
4099
4100
|
(O token será mantido apenas em memória nesta sessão)`
|
|
4100
4101
|
);
|
|
4101
|
-
if (!
|
|
4102
|
+
if (!r || !r.trim())
|
|
4102
4103
|
return;
|
|
4103
|
-
e =
|
|
4104
|
+
e = r.trim(), $.sessionGithubToken = e;
|
|
4104
4105
|
}
|
|
4105
4106
|
try {
|
|
4106
|
-
const
|
|
4107
|
+
const r = await this.recorder.getArtifact(t), n = await gt(r, e), a = `${this.getViewerUrl()}/?gist=${n.gistId}`;
|
|
4107
4108
|
let s = !1;
|
|
4108
4109
|
if (typeof navigator < "u" && navigator.clipboard && navigator.clipboard.writeText)
|
|
4109
4110
|
try {
|
|
@@ -4118,21 +4119,21 @@ const ae = `
|
|
|
4118
4119
|
s = !1;
|
|
4119
4120
|
}
|
|
4120
4121
|
s ? this.showToast("Link copiado.", "success") : prompt("Link compartilhado gerado com sucesso:", a);
|
|
4121
|
-
} catch (
|
|
4122
|
-
(
|
|
4122
|
+
} catch (r) {
|
|
4123
|
+
(r instanceof Error ? r.message : String(r)).includes("401") && ($.sessionGithubToken = null), this.showBanner("Não foi possível gerar o link. Tente novamente.", "danger");
|
|
4123
4124
|
}
|
|
4124
4125
|
}
|
|
4125
4126
|
handleAnnotate() {
|
|
4126
4127
|
this.isOpen = !1, this.render(), new ie().open(async (e) => {
|
|
4127
|
-
var
|
|
4128
|
+
var r;
|
|
4128
4129
|
if (!e) {
|
|
4129
4130
|
this.isOpen = !0, this.render();
|
|
4130
4131
|
return;
|
|
4131
4132
|
}
|
|
4132
4133
|
try {
|
|
4133
4134
|
this.isCapturing = !0, this.isOpen = !0, this.render();
|
|
4134
|
-
const
|
|
4135
|
-
await this.recorder.capture(
|
|
4135
|
+
const n = (r = e.notes) != null && r.trim() ? `Anotação do QA: ${e.notes.trim()}` : "Anotação visual de bug na tela", i = this.selectedDurationSeconds > 0 ? this.selectedDurationSeconds : void 0;
|
|
4136
|
+
await this.recorder.capture(n, i, {
|
|
4136
4137
|
annotationImage: e.dataUrl,
|
|
4137
4138
|
notes: e.notes
|
|
4138
4139
|
}), await this.updateData(), this.showToast("Gravação salva.", "success");
|
|
@@ -4154,13 +4155,13 @@ const ae = `
|
|
|
4154
4155
|
}
|
|
4155
4156
|
openInViewer(t) {
|
|
4156
4157
|
const e = this.getViewerUrl();
|
|
4157
|
-
let
|
|
4158
|
+
let r = "*", n = e;
|
|
4158
4159
|
try {
|
|
4159
4160
|
const p = new URL(e, window.location.href);
|
|
4160
|
-
|
|
4161
|
+
r = p.origin, p.searchParams.set("openerOrigin", window.location.origin), n = p.toString();
|
|
4161
4162
|
} catch {
|
|
4162
4163
|
}
|
|
4163
|
-
const i = window.open(
|
|
4164
|
+
const i = window.open(n, "backtrack_viewer");
|
|
4164
4165
|
if (!i) {
|
|
4165
4166
|
this.showBanner("Pop-up bloqueado. Permita pop-ups no navegador.", "danger");
|
|
4166
4167
|
return;
|
|
@@ -4178,12 +4179,12 @@ const ae = `
|
|
|
4178
4179
|
return;
|
|
4179
4180
|
}
|
|
4180
4181
|
try {
|
|
4181
|
-
i.postMessage({ type: "LOAD_BACKTRACK_ARTIFACT", artifact: t },
|
|
4182
|
+
i.postMessage({ type: "LOAD_BACKTRACK_ARTIFACT", artifact: t }, r);
|
|
4182
4183
|
} catch {
|
|
4183
4184
|
}
|
|
4184
4185
|
}, h = (p) => {
|
|
4185
|
-
var
|
|
4186
|
-
p.source === i && (
|
|
4186
|
+
var g, b, f, m;
|
|
4187
|
+
p.source === i && (r !== "*" && p.origin !== r || (((g = p.data) == null ? void 0 : g.type) === "BACKTRACK_VIEWER_READY" || ((b = p.data) == null ? void 0 : b.type) === "FFR_VIEWER_READY" ? c() : (((f = p.data) == null ? void 0 : f.type) === "BACKTRACK_ARTIFACT_RECEIVED" || ((m = p.data) == null ? void 0 : m.type) === "FFR_ARTIFACT_RECEIVED") && (a = !0, o())));
|
|
4187
4188
|
};
|
|
4188
4189
|
window.addEventListener("message", h), c();
|
|
4189
4190
|
const u = Date.now();
|
|
@@ -4200,7 +4201,27 @@ const ae = `
|
|
|
4200
4201
|
return e < 1024 ? `${e.toFixed(1)} KB` : `${(e / 1024).toFixed(1)} MB`;
|
|
4201
4202
|
}
|
|
4202
4203
|
formatIncidentTitle(t) {
|
|
4203
|
-
|
|
4204
|
+
const { reason: e, trigger: r } = t;
|
|
4205
|
+
if (!e || e === "manual")
|
|
4206
|
+
return "Sessão manual iniciada";
|
|
4207
|
+
let i = {
|
|
4208
|
+
error: "Erro na aplicação",
|
|
4209
|
+
"unhandled-error": "Erro não tratado na aplicação",
|
|
4210
|
+
unhandledrejection: "Promise não tratada",
|
|
4211
|
+
react: "Erro no React",
|
|
4212
|
+
http: "Falha na requisição de rede",
|
|
4213
|
+
"http-error": "Falha na requisição de rede"
|
|
4214
|
+
}[e] || e;
|
|
4215
|
+
const a = r == null ? void 0 : r.detail;
|
|
4216
|
+
if (e === "http" && a) {
|
|
4217
|
+
if (i = typeof a.status == "number" && a.status > 0 ? `HTTP ${a.status}` : "Falha de rede", typeof a.method == "string" && typeof a.url == "string")
|
|
4218
|
+
try {
|
|
4219
|
+
const s = new URL(a.url, "http://localhost").pathname;
|
|
4220
|
+
i += ` · ${a.method.toUpperCase()} ${s}`;
|
|
4221
|
+
} catch {
|
|
4222
|
+
}
|
|
4223
|
+
} else typeof (a == null ? void 0 : a.message) == "string" && a.message.trim() && (i += ` · ${a.message.trim()}`);
|
|
4224
|
+
return i.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4204
4225
|
}
|
|
4205
4226
|
renderBannerHtml() {
|
|
4206
4227
|
if (!this.banner) return "";
|
|
@@ -4259,7 +4280,7 @@ const ae = `
|
|
|
4259
4280
|
`;
|
|
4260
4281
|
}
|
|
4261
4282
|
renderPanelContentHtml() {
|
|
4262
|
-
var e,
|
|
4283
|
+
var e, r, n, i;
|
|
4263
4284
|
const t = this.incidents.length;
|
|
4264
4285
|
return `
|
|
4265
4286
|
<!-- 1. Header -->
|
|
@@ -4278,7 +4299,7 @@ const ae = `
|
|
|
4278
4299
|
<div class="backtrack-header-right">
|
|
4279
4300
|
<span
|
|
4280
4301
|
class="backtrack-storage-tooltip-trigger"
|
|
4281
|
-
title="${(e = this.health) != null && e.protectedStorageBytes ? `${this.formatBytes(this.health.protectedStorageBytes)} protegidos. ` : ""}${(
|
|
4302
|
+
title="${(e = this.health) != null && e.protectedStorageBytes ? `${this.formatBytes(this.health.protectedStorageBytes)} protegidos. ` : ""}${(r = this.health) != null && r.protectedStorageExceeded ? "Limite excedido por incidentes protegidos. Exclua incidentes para liberar espaço. " : ""}Dados protegidos contra a rotação automática de memória no IndexedDB (limite total de 50 MB)."
|
|
4282
4303
|
aria-label="Informações sobre dados protegidos no IndexedDB"
|
|
4283
4304
|
>
|
|
4284
4305
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -4302,7 +4323,7 @@ const ae = `
|
|
|
4302
4323
|
${this.isHeaderMenuOpen ? `
|
|
4303
4324
|
<div class="backtrack-header-menu">
|
|
4304
4325
|
<div class="backtrack-header-menu-info">
|
|
4305
|
-
Armazenamento: ${this.formatBytes(((
|
|
4326
|
+
Armazenamento: ${this.formatBytes(((n = this.health) == null ? void 0 : n.storageBytes) ?? 0)}${(i = this.health) != null && i.browserStorageEstimateBytes ? ` (Navegador: ${this.formatBytes(this.health.browserStorageEstimateBytes)})` : ""}
|
|
4306
4327
|
</div>
|
|
4307
4328
|
<button type="button" class="backtrack-header-menu-item" id="btn-hide-widget">
|
|
4308
4329
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -4470,16 +4491,16 @@ const ae = `
|
|
|
4470
4491
|
t || (t = document.createElement("style"), t.textContent = ae, this.shadow.appendChild(t));
|
|
4471
4492
|
let e = this.shadow.querySelector(".backtrack-root");
|
|
4472
4493
|
e || (e = document.createElement("div"), e.className = "backtrack-root", this.shadow.appendChild(e));
|
|
4473
|
-
const
|
|
4494
|
+
const r = ((s = this.health) == null ? void 0 : s.state) === "recording" ? "backtrack-status-recording" : ((o = this.health) == null ? void 0 : o.state) === "degraded" ? "backtrack-status-degraded" : "backtrack-status-idle", n = this.incidents.length;
|
|
4474
4495
|
let i = e.querySelector("#btn-launcher");
|
|
4475
4496
|
if (i) {
|
|
4476
4497
|
const c = i.querySelector(".backtrack-launcher-status-dot");
|
|
4477
|
-
c && (c.className = `backtrack-launcher-status-dot ${
|
|
4498
|
+
c && (c.className = `backtrack-launcher-status-dot ${r}`);
|
|
4478
4499
|
let h = i.querySelector(".backtrack-incident-badge-count");
|
|
4479
|
-
|
|
4500
|
+
n > 0 ? (h || (h = document.createElement("span"), h.className = "backtrack-incident-badge-count", i.appendChild(h)), h.textContent = String(n)) : h && h.remove();
|
|
4480
4501
|
} else {
|
|
4481
4502
|
const c = document.createElement("div");
|
|
4482
|
-
c.innerHTML = this.renderLauncherHtml(
|
|
4503
|
+
c.innerHTML = this.renderLauncherHtml(r, n), i = c.firstElementChild, e.appendChild(i), this.attachLauncherListeners(i);
|
|
4483
4504
|
}
|
|
4484
4505
|
let a = e.querySelector(".backtrack-panel");
|
|
4485
4506
|
if (!this.isOpen)
|
|
@@ -4508,12 +4529,12 @@ const ae = `
|
|
|
4508
4529
|
<div class="backtrack-empty-desc">Clique em Salvar para capturar os últimos 5 minutos</div>
|
|
4509
4530
|
</div>
|
|
4510
4531
|
` : this.incidents.slice(0, 8).map((e) => {
|
|
4511
|
-
const
|
|
4532
|
+
const r = new Date(e.startedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" }), n = e.finalizedAt ? Math.max(1, Math.round((e.finalizedAt - e.startedAt) / 1e3)) : 0, i = this.formatIncidentTitle(e);
|
|
4512
4533
|
return `
|
|
4513
4534
|
<div class="backtrack-list-item" data-open-detail-id="${e.id}" role="button" tabindex="0" aria-label="${i}">
|
|
4514
4535
|
<div class="backtrack-item-content">
|
|
4515
4536
|
<span class="backtrack-item-title">${i}</span>
|
|
4516
|
-
<span class="backtrack-item-meta">${
|
|
4537
|
+
<span class="backtrack-item-meta">${r} · ${n}s</span>
|
|
4517
4538
|
</div>
|
|
4518
4539
|
<div class="backtrack-item-chevron">
|
|
4519
4540
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
@@ -4528,7 +4549,7 @@ const ae = `
|
|
|
4528
4549
|
const t = this.incidents.find((i) => i.id === this.selectedIncidentId);
|
|
4529
4550
|
if (!t)
|
|
4530
4551
|
return this.selectedIncidentId = null, this.renderIncidentsHtml();
|
|
4531
|
-
const e = new Date(t.startedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" }),
|
|
4552
|
+
const e = new Date(t.startedAt).toLocaleTimeString("pt-BR", { hour: "2-digit", minute: "2-digit" }), r = t.finalizedAt ? Math.max(1, Math.round((t.finalizedAt - t.startedAt) / 1e3)) : 0;
|
|
4532
4553
|
return `
|
|
4533
4554
|
<div class="backtrack-detail-view">
|
|
4534
4555
|
<!-- 1. Botão Voltar -->
|
|
@@ -4544,8 +4565,8 @@ const ae = `
|
|
|
4544
4565
|
|
|
4545
4566
|
<!-- 2. Card de resumo da sessão -->
|
|
4546
4567
|
<div class="backtrack-detail-card">
|
|
4547
|
-
<div class="backtrack-detail-title">${this.formatIncidentTitle(t
|
|
4548
|
-
<div class="backtrack-detail-meta">${e} · ${
|
|
4568
|
+
<div class="backtrack-detail-title">${this.formatIncidentTitle(t)}</div>
|
|
4569
|
+
<div class="backtrack-detail-meta">${e} · ${r}s · ${t.id.length > 20 ? t.id.substring(0, 18) + "..." : t.id}</div>
|
|
4549
4570
|
</div>
|
|
4550
4571
|
|
|
4551
4572
|
<!-- 3. CTA principal — Visualizar replay -->
|
|
@@ -4753,12 +4774,12 @@ const ae = `
|
|
|
4753
4774
|
this.render();
|
|
4754
4775
|
return;
|
|
4755
4776
|
}
|
|
4756
|
-
const e = ((i = this.health) == null ? void 0 : i.state) === "recording" ? "backtrack-status-recording" : ((a = this.health) == null ? void 0 : a.state) === "degraded" ? "backtrack-status-degraded" : "backtrack-status-idle",
|
|
4757
|
-
|
|
4758
|
-
const
|
|
4759
|
-
if (
|
|
4760
|
-
let s =
|
|
4761
|
-
this.incidents.length > 0 ? (s || (s = document.createElement("span"), s.className = "backtrack-incident-badge-count",
|
|
4777
|
+
const e = ((i = this.health) == null ? void 0 : i.state) === "recording" ? "backtrack-status-recording" : ((a = this.health) == null ? void 0 : a.state) === "degraded" ? "backtrack-status-degraded" : "backtrack-status-idle", r = this.shadow.querySelector(".backtrack-launcher-status-dot");
|
|
4778
|
+
r && (r.className = `backtrack-launcher-status-dot ${e}`);
|
|
4779
|
+
const n = this.shadow.getElementById("btn-launcher");
|
|
4780
|
+
if (n) {
|
|
4781
|
+
let s = n.querySelector(".backtrack-incident-badge-count");
|
|
4782
|
+
this.incidents.length > 0 ? (s || (s = document.createElement("span"), s.className = "backtrack-incident-badge-count", n.appendChild(s)), s.textContent = String(this.incidents.length)) : s && s.remove();
|
|
4762
4783
|
}
|
|
4763
4784
|
if (this.isOpen && t) {
|
|
4764
4785
|
const s = this.shadow.getElementById("backtrack-saved-count-title");
|
|
@@ -4776,51 +4797,51 @@ const ae = `
|
|
|
4776
4797
|
attachIncidentListeners() {
|
|
4777
4798
|
var t;
|
|
4778
4799
|
this.shadow && (this.shadow.querySelectorAll("[data-open-detail-id]").forEach((e) => {
|
|
4779
|
-
e.addEventListener("click", (
|
|
4780
|
-
const
|
|
4781
|
-
|
|
4800
|
+
e.addEventListener("click", (r) => {
|
|
4801
|
+
const n = r.currentTarget.getAttribute("data-open-detail-id");
|
|
4802
|
+
n && (this.selectedIncidentId = n, this.render());
|
|
4782
4803
|
});
|
|
4783
4804
|
}), (t = this.shadow.getElementById("btn-back-to-list")) == null || t.addEventListener("click", () => {
|
|
4784
4805
|
this.selectedIncidentId = null, this.render();
|
|
4785
4806
|
}), this.shadow.querySelectorAll("[data-view-id]").forEach((e) => {
|
|
4786
|
-
e.addEventListener("click", (
|
|
4787
|
-
const
|
|
4788
|
-
|
|
4807
|
+
e.addEventListener("click", (r) => {
|
|
4808
|
+
const n = r.currentTarget.getAttribute("data-view-id");
|
|
4809
|
+
n && this.handleViewIncident(n);
|
|
4789
4810
|
});
|
|
4790
4811
|
}), this.shadow.querySelectorAll("[data-share-gist-id]").forEach((e) => {
|
|
4791
|
-
e.addEventListener("click", (
|
|
4792
|
-
const
|
|
4793
|
-
|
|
4812
|
+
e.addEventListener("click", (r) => {
|
|
4813
|
+
const n = r.currentTarget.getAttribute("data-share-gist-id");
|
|
4814
|
+
n && this.handleShareGist(n);
|
|
4794
4815
|
});
|
|
4795
4816
|
}), this.shadow.querySelectorAll("[data-download-id]").forEach((e) => {
|
|
4796
|
-
e.addEventListener("click", (
|
|
4797
|
-
const
|
|
4798
|
-
|
|
4817
|
+
e.addEventListener("click", (r) => {
|
|
4818
|
+
const n = r.currentTarget.getAttribute("data-download-id");
|
|
4819
|
+
n && this.handleDownloadIncident(n);
|
|
4799
4820
|
});
|
|
4800
4821
|
}), this.shadow.querySelectorAll("[data-copy-id]").forEach((e) => {
|
|
4801
|
-
e.addEventListener("click", (
|
|
4802
|
-
const
|
|
4803
|
-
|
|
4822
|
+
e.addEventListener("click", (r) => {
|
|
4823
|
+
const n = r.currentTarget.getAttribute("data-copy-id");
|
|
4824
|
+
n && this.handleCopyMarkdown(n);
|
|
4804
4825
|
});
|
|
4805
4826
|
}), this.shadow.querySelectorAll("[data-delete-id]").forEach((e) => {
|
|
4806
|
-
e.addEventListener("click", (
|
|
4807
|
-
const
|
|
4808
|
-
|
|
4827
|
+
e.addEventListener("click", (r) => {
|
|
4828
|
+
const n = r.currentTarget.getAttribute("data-delete-id");
|
|
4829
|
+
n && this.handleDeleteIncident(n);
|
|
4809
4830
|
});
|
|
4810
4831
|
}));
|
|
4811
4832
|
}
|
|
4812
4833
|
attachLauncherListeners(t) {
|
|
4813
4834
|
if (t.dataset.hasListeners) return;
|
|
4814
4835
|
t.dataset.hasListeners = "true";
|
|
4815
|
-
let e = 0,
|
|
4836
|
+
let e = 0, r = 0, n = 0, i = 0, a = !1;
|
|
4816
4837
|
t.addEventListener(
|
|
4817
4838
|
"touchstart",
|
|
4818
4839
|
(s) => {
|
|
4819
4840
|
if (s.touches.length === 1 && this.container) {
|
|
4820
4841
|
const o = s.touches[0];
|
|
4821
|
-
e = o.clientX,
|
|
4842
|
+
e = o.clientX, r = o.clientY;
|
|
4822
4843
|
const c = this.container.getBoundingClientRect();
|
|
4823
|
-
|
|
4844
|
+
n = c.left, i = c.top, a = !1;
|
|
4824
4845
|
}
|
|
4825
4846
|
},
|
|
4826
4847
|
{ passive: !0 }
|
|
@@ -4828,8 +4849,8 @@ const ae = `
|
|
|
4828
4849
|
"touchmove",
|
|
4829
4850
|
(s) => {
|
|
4830
4851
|
if (s.touches.length === 1 && this.container) {
|
|
4831
|
-
const o = s.touches[0], c = o.clientX - e, h = o.clientY -
|
|
4832
|
-
(Math.abs(c) > 5 || Math.abs(h) > 5) && (a = !0, this.container.style.left = `${
|
|
4852
|
+
const o = s.touches[0], c = o.clientX - e, h = o.clientY - r;
|
|
4853
|
+
(Math.abs(c) > 5 || Math.abs(h) > 5) && (a = !0, this.container.style.left = `${n + c}px`, this.container.style.top = `${i + h}px`, this.container.style.bottom = "auto", this.container.style.right = "auto");
|
|
4833
4854
|
}
|
|
4834
4855
|
},
|
|
4835
4856
|
{ passive: !0 }
|
|
@@ -4846,13 +4867,13 @@ const ae = `
|
|
|
4846
4867
|
});
|
|
4847
4868
|
}
|
|
4848
4869
|
attachPanelListeners() {
|
|
4849
|
-
var e,
|
|
4870
|
+
var e, r, n, i, a, s, o, c, h, u, p, g, b, f, m, k, I, y, w, E, S, C, M, A, _;
|
|
4850
4871
|
if (!this.shadow) return;
|
|
4851
4872
|
(e = this.shadow.getElementById("btn-close")) == null || e.addEventListener("click", () => {
|
|
4852
4873
|
this.toggleOpen();
|
|
4853
|
-
}), (
|
|
4874
|
+
}), (r = this.shadow.getElementById("btn-dismiss-banner")) == null || r.addEventListener("click", () => {
|
|
4854
4875
|
this.dismissBanner();
|
|
4855
|
-
}), (
|
|
4876
|
+
}), (n = this.shadow.getElementById("btn-header-menu")) == null || n.addEventListener("click", (B) => {
|
|
4856
4877
|
B.stopPropagation(), this.isHeaderMenuOpen = !this.isHeaderMenuOpen, this.render();
|
|
4857
4878
|
}), (i = this.shadow.getElementById("btn-hide-widget")) == null || i.addEventListener("click", (B) => {
|
|
4858
4879
|
B.stopPropagation(), this.isHeaderMenuOpen = !1, this.showHideConfirmModal = !0, this.render();
|
|
@@ -4870,17 +4891,17 @@ const ae = `
|
|
|
4870
4891
|
const z = parseInt(B.target.value, 10);
|
|
4871
4892
|
isNaN(z) || (this.selectedDurationSeconds = Math.max(5, Math.min(900, z)));
|
|
4872
4893
|
}), t.addEventListener("change", (B) => {
|
|
4873
|
-
const z = parseInt(B.target.value, 10),
|
|
4874
|
-
this.selectedDurationSeconds =
|
|
4894
|
+
const z = parseInt(B.target.value, 10), j = isNaN(z) ? 60 : Math.max(5, Math.min(900, z));
|
|
4895
|
+
this.selectedDurationSeconds = j, t.value = String(j);
|
|
4875
4896
|
})), (h = this.shadow.getElementById("btn-save")) == null || h.addEventListener("click", () => {
|
|
4876
4897
|
this.handleCapture();
|
|
4877
4898
|
}), (u = this.shadow.getElementById("btn-annotate")) == null || u.addEventListener("click", () => {
|
|
4878
4899
|
this.handleAnnotate();
|
|
4879
4900
|
}), (p = this.shadow.getElementById("btn-clear")) == null || p.addEventListener("click", () => {
|
|
4880
4901
|
this.handleClear();
|
|
4881
|
-
}), this.attachIncidentListeners(), this.exportModalIncidentId && ((
|
|
4902
|
+
}), this.attachIncidentListeners(), this.exportModalIncidentId && ((g = this.shadow.getElementById("btn-close-export-modal")) == null || g.addEventListener("click", () => {
|
|
4882
4903
|
this.closeExportModal();
|
|
4883
|
-
}), (
|
|
4904
|
+
}), (b = this.shadow.getElementById("btn-cancel-export-modal")) == null || b.addEventListener("click", () => {
|
|
4884
4905
|
this.closeExportModal();
|
|
4885
4906
|
}), (f = this.shadow.getElementById("check-include-incident-link")) == null || f.addEventListener("change", (B) => {
|
|
4886
4907
|
this.exportModalIncludeLink = B.target.checked, this.render();
|
|
@@ -4914,7 +4935,7 @@ const ae = `
|
|
|
4914
4935
|
};
|
|
4915
4936
|
l($, "sessionGithubToken", null);
|
|
4916
4937
|
let J = $;
|
|
4917
|
-
const ft = "0.5.
|
|
4938
|
+
const ft = "0.5.2", v = class v {
|
|
4918
4939
|
constructor(t, e) {
|
|
4919
4940
|
l(this, "options");
|
|
4920
4941
|
l(this, "stateMachine");
|
|
@@ -4942,7 +4963,7 @@ const ft = "0.5.1", v = class v {
|
|
|
4942
4963
|
l(this, "cachedBrowserQuotaBytes");
|
|
4943
4964
|
l(this, "nextSequence", () => (this.sequence++, this.sequence));
|
|
4944
4965
|
l(this, "stoppingPromise");
|
|
4945
|
-
var
|
|
4966
|
+
var r, n, i, a, s, o, c, h, u, p, g;
|
|
4946
4967
|
this.options = {
|
|
4947
4968
|
bufferMinutes: (t == null ? void 0 : t.bufferMinutes) ?? 5,
|
|
4948
4969
|
afterErrorSeconds: (t == null ? void 0 : t.afterErrorSeconds) ?? 15,
|
|
@@ -4954,8 +4975,8 @@ const ft = "0.5.1", v = class v {
|
|
|
4954
4975
|
recorderVersion: t == null ? void 0 : t.recorderVersion,
|
|
4955
4976
|
ignoredUrls: t == null ? void 0 : t.ignoredUrls,
|
|
4956
4977
|
network: {
|
|
4957
|
-
capturePayloads: ((
|
|
4958
|
-
maxPayloadSize: ((
|
|
4978
|
+
capturePayloads: ((r = t == null ? void 0 : t.network) == null ? void 0 : r.capturePayloads) ?? !1,
|
|
4979
|
+
maxPayloadSize: ((n = t == null ? void 0 : t.network) == null ? void 0 : n.maxPayloadSize) ?? 64 * 1024
|
|
4959
4980
|
},
|
|
4960
4981
|
privacy: {
|
|
4961
4982
|
maskAllInputs: ((i = t == null ? void 0 : t.privacy) == null ? void 0 : i.maskAllInputs) ?? !0,
|
|
@@ -4966,7 +4987,7 @@ const ft = "0.5.1", v = class v {
|
|
|
4966
4987
|
sanitizeUrl: (h = t == null ? void 0 : t.privacy) == null ? void 0 : h.sanitizeUrl,
|
|
4967
4988
|
sensitiveRoutes: (u = t == null ? void 0 : t.privacy) == null ? void 0 : u.sensitiveRoutes,
|
|
4968
4989
|
autoMaskPII: (p = t == null ? void 0 : t.privacy) == null ? void 0 : p.autoMaskPII,
|
|
4969
|
-
recordCanvas: (
|
|
4990
|
+
recordCanvas: (g = t == null ? void 0 : t.privacy) == null ? void 0 : g.recordCanvas
|
|
4970
4991
|
},
|
|
4971
4992
|
storage: t == null ? void 0 : t.storage,
|
|
4972
4993
|
sessionOptions: t == null ? void 0 : t.sessionOptions,
|
|
@@ -4983,12 +5004,12 @@ const ft = "0.5.1", v = class v {
|
|
|
4983
5004
|
static async init(t, e) {
|
|
4984
5005
|
if (v.activeInstance)
|
|
4985
5006
|
return v.activeInstance;
|
|
4986
|
-
const
|
|
4987
|
-
if (await
|
|
4988
|
-
const
|
|
4989
|
-
|
|
5007
|
+
const r = new v(t, e);
|
|
5008
|
+
if (await r.start(), v.activeInstance = r, typeof window < "u") {
|
|
5009
|
+
const n = window;
|
|
5010
|
+
n.Backtrack = v, n.flightRecorder = r, n.hideBacktrack = () => v.hideWidget(), n.showBacktrack = () => v.showWidget(), n.toggleBacktrack = () => v.toggleWidget();
|
|
4990
5011
|
}
|
|
4991
|
-
return
|
|
5012
|
+
return r;
|
|
4992
5013
|
}
|
|
4993
5014
|
static hideWidget() {
|
|
4994
5015
|
const t = v.activeInstance;
|
|
@@ -5068,7 +5089,7 @@ const ft = "0.5.1", v = class v {
|
|
|
5068
5089
|
};
|
|
5069
5090
|
}
|
|
5070
5091
|
async start() {
|
|
5071
|
-
var t, e,
|
|
5092
|
+
var t, e, r, n;
|
|
5072
5093
|
if (!this.stateMachine.isRecording())
|
|
5073
5094
|
try {
|
|
5074
5095
|
await this.db.open();
|
|
@@ -5147,17 +5168,17 @@ const ft = "0.5.1", v = class v {
|
|
|
5147
5168
|
ignoredUrls: this.options.ignoredUrls,
|
|
5148
5169
|
sanitizeUrlCallback: (t = this.options.privacy) == null ? void 0 : t.sanitizeUrl,
|
|
5149
5170
|
capturePayloads: (e = this.options.network) == null ? void 0 : e.capturePayloads,
|
|
5150
|
-
maxPayloadSize: (
|
|
5171
|
+
maxPayloadSize: (r = this.options.network) == null ? void 0 : r.maxPayloadSize
|
|
5151
5172
|
}
|
|
5152
5173
|
), this.navigationCapturer = new Zt(
|
|
5153
5174
|
this.writer,
|
|
5154
5175
|
this.nextSequence,
|
|
5155
5176
|
{
|
|
5156
|
-
sanitizeUrlCallback: (
|
|
5177
|
+
sanitizeUrlCallback: (n = this.options.privacy) == null ? void 0 : n.sanitizeUrl
|
|
5157
5178
|
}
|
|
5158
|
-
), this.rrwebCapturer = new
|
|
5179
|
+
), this.rrwebCapturer = new re(this.writer, {
|
|
5159
5180
|
privacy: this.options.privacy
|
|
5160
|
-
}), this.performanceCapturer = new
|
|
5181
|
+
}), this.performanceCapturer = new ne(this.writer, this.nextSequence), this.consoleCapturer.start(), this.errorCapturer.start(), this.networkCapturer.start(), this.navigationCapturer.start(), this.rrwebCapturer.start(), this.performanceCapturer.start(), this.stateMachine.transition({ type: "START" }), this.incidentManager.getPendingIncident() && this.stateMachine.transition({ type: "TRIGGER_AUTO" }), this.retentionIntervalTimer = setInterval(() => {
|
|
5161
5182
|
this.scheduleRetention();
|
|
5162
5183
|
}, 3e4), this.updateStatsCache(), this.options.showWidget && typeof window < "u" && (this.widget = new J(this, this.options.widgetOptions), this.widget.mount()), typeof window < "u" && typeof window.addEventListener == "function" && (this.pageHideHandler = () => {
|
|
5163
5184
|
var c;
|
|
@@ -5199,15 +5220,15 @@ const ft = "0.5.1", v = class v {
|
|
|
5199
5220
|
async handleQuotaExceeded() {
|
|
5200
5221
|
try {
|
|
5201
5222
|
this.incidentManager ? await this.incidentManager.runExclusive(async () => {
|
|
5202
|
-
var
|
|
5203
|
-
await ((
|
|
5223
|
+
var n;
|
|
5224
|
+
await ((n = this.incidentManager) == null ? void 0 : n.protectSessionChunks()), await this.retention.emergencyPrune(), await this.updateStatsCache();
|
|
5204
5225
|
}) : (await this.retention.emergencyPrune(), await this.updateStatsCache());
|
|
5205
5226
|
} catch {
|
|
5206
5227
|
}
|
|
5207
|
-
const t = await this.retention.getStorageBreakdown().catch(() => null),
|
|
5228
|
+
const t = await this.retention.getStorageBreakdown().catch(() => null), r = (t ? t.bufferBytes === 0 && t.protectedBytes > 0 : !1) || t != null && t.protectedExceedsLimit ? "A quota do navegador foi excedida. Apenas conteúdo protegido permanece salvo; é necessário excluir incidentes ou limpar gravações para liberar espaço." : "A quota do navegador impediu a gravação de um lote. Um prune emergencial de dados não protegidos foi executado.";
|
|
5208
5229
|
this.stateMachine.transition({
|
|
5209
5230
|
type: "DEGRADE",
|
|
5210
|
-
reason:
|
|
5231
|
+
reason: r
|
|
5211
5232
|
});
|
|
5212
5233
|
}
|
|
5213
5234
|
async updateStatsCache() {
|
|
@@ -5227,7 +5248,7 @@ const ft = "0.5.1", v = class v {
|
|
|
5227
5248
|
else if (!t.isOverLimit && this.stateMachine.isDegraded()) {
|
|
5228
5249
|
const e = this.stateMachine.getDegradedReasons();
|
|
5229
5250
|
e.every(
|
|
5230
|
-
(
|
|
5251
|
+
(n) => n.includes("maxStorageMb") || n.includes("quota") || n.includes("Quota") || n.includes("armazenamento")
|
|
5231
5252
|
) && e.length > 0 && this.stateMachine.transition({ type: "RECOVER" });
|
|
5232
5253
|
}
|
|
5233
5254
|
} catch {
|
|
@@ -5237,14 +5258,14 @@ const ft = "0.5.1", v = class v {
|
|
|
5237
5258
|
const e = this.options.transport;
|
|
5238
5259
|
if (e)
|
|
5239
5260
|
try {
|
|
5240
|
-
const
|
|
5241
|
-
|
|
5261
|
+
const r = await this.getArtifact(t), n = this.options.beforeSend ? await this.options.beforeSend(r) : r;
|
|
5262
|
+
n && await e.send(n);
|
|
5242
5263
|
} catch {
|
|
5243
5264
|
}
|
|
5244
5265
|
}
|
|
5245
5266
|
stopCapturers() {
|
|
5246
|
-
var t, e,
|
|
5247
|
-
(t = this.rrwebCapturer) == null || t.stop(), (e = this.navigationCapturer) == null || e.stop(), (
|
|
5267
|
+
var t, e, r, n, i, a;
|
|
5268
|
+
(t = this.rrwebCapturer) == null || t.stop(), (e = this.navigationCapturer) == null || e.stop(), (r = this.networkCapturer) == null || r.stop(), (n = this.errorCapturer) == null || n.stop(), (i = this.consoleCapturer) == null || i.stop(), (a = this.performanceCapturer) == null || a.stop();
|
|
5248
5269
|
}
|
|
5249
5270
|
clearRuntimeReferences() {
|
|
5250
5271
|
this.rrwebCapturer = null, this.navigationCapturer = null, this.networkCapturer = null, this.errorCapturer = null, this.consoleCapturer = null, this.performanceCapturer = null, this.writer = null, this.incidentManager = null;
|
|
@@ -5269,10 +5290,10 @@ const ft = "0.5.1", v = class v {
|
|
|
5269
5290
|
}
|
|
5270
5291
|
}
|
|
5271
5292
|
}
|
|
5272
|
-
async capture(t = "manual", e,
|
|
5293
|
+
async capture(t = "manual", e, r) {
|
|
5273
5294
|
if (!this.incidentManager || !this.writer)
|
|
5274
5295
|
throw new Error("FlightRecorder não está em execução.");
|
|
5275
|
-
const
|
|
5296
|
+
const n = await this.incidentManager.runExclusive(async () => {
|
|
5276
5297
|
const i = Date.now();
|
|
5277
5298
|
return this.writer.addTimelineEvent({
|
|
5278
5299
|
id: `marker_manual_${i}`,
|
|
@@ -5289,15 +5310,15 @@ const ft = "0.5.1", v = class v {
|
|
|
5289
5310
|
detail: {
|
|
5290
5311
|
userReason: t,
|
|
5291
5312
|
windowSeconds: e,
|
|
5292
|
-
annotationImage:
|
|
5293
|
-
notes:
|
|
5294
|
-
annotations:
|
|
5313
|
+
annotationImage: r == null ? void 0 : r.annotationImage,
|
|
5314
|
+
notes: r == null ? void 0 : r.notes,
|
|
5315
|
+
annotations: r == null ? void 0 : r.annotations
|
|
5295
5316
|
}
|
|
5296
5317
|
},
|
|
5297
5318
|
e
|
|
5298
5319
|
);
|
|
5299
5320
|
});
|
|
5300
|
-
return await this.updateStatsCache(),
|
|
5321
|
+
return await this.updateStatsCache(), n;
|
|
5301
5322
|
}
|
|
5302
5323
|
captureException(t, e) {
|
|
5303
5324
|
if (this.errorCapturer)
|
|
@@ -5322,19 +5343,19 @@ const ft = "0.5.1", v = class v {
|
|
|
5322
5343
|
}).exportArtifact(t);
|
|
5323
5344
|
}
|
|
5324
5345
|
async exportIncident(t, e) {
|
|
5325
|
-
const
|
|
5326
|
-
...
|
|
5346
|
+
const r = await this.getArtifact(t), n = new Date(r.incident.triggeredAt).toISOString().replace(/:/g, "-").replace(/\..+/, ""), i = (e == null ? void 0 : e.aiOptimized) ?? !1, a = !i && ((e == null ? void 0 : e.compress) ?? !1), s = i ? ".ai.json" : a ? ".ffr.json.gz" : ".ffr.json", o = `flight-recorder-${n}-${r.incident.reason}-${t}${s}`, c = i ? {
|
|
5347
|
+
...r,
|
|
5327
5348
|
replay: [],
|
|
5328
5349
|
_aiNote: "Replay visual removido para otimizacao de IA. Timeline, erros de console e rede preservados."
|
|
5329
|
-
} :
|
|
5350
|
+
} : r;
|
|
5330
5351
|
if (typeof window < "u" && typeof document < "u") {
|
|
5331
5352
|
let h;
|
|
5332
5353
|
if (a) {
|
|
5333
|
-
const
|
|
5334
|
-
h = new Blob([
|
|
5354
|
+
const g = await Dt(r);
|
|
5355
|
+
h = new Blob([g], { type: "application/gzip" });
|
|
5335
5356
|
} else {
|
|
5336
|
-
const
|
|
5337
|
-
h = new Blob([
|
|
5357
|
+
const g = JSON.stringify(c, null, 2);
|
|
5358
|
+
h = new Blob([g], { type: "application/json;charset=utf-8" });
|
|
5338
5359
|
}
|
|
5339
5360
|
const u = URL.createObjectURL(h), p = document.createElement("a");
|
|
5340
5361
|
p.href = u, p.download = o, document.body.appendChild(p), p.click(), document.body.removeChild(p), URL.revokeObjectURL(u);
|
|
@@ -5355,8 +5376,8 @@ const ft = "0.5.1", v = class v {
|
|
|
5355
5376
|
this.incidentManager && await this.incidentManager.reset(), this.stateMachine.getState() === "incident_pending" && this.stateMachine.transition({ type: "FINALIZE_INCIDENT" }), await this.db.clearAll(), this.cachedStorageBytes = 0, this.cachedProtectedBytes = 0, this.cachedIncidentCount = 0;
|
|
5356
5377
|
}
|
|
5357
5378
|
getHealth() {
|
|
5358
|
-
var
|
|
5359
|
-
const t = ((
|
|
5379
|
+
var r, n;
|
|
5380
|
+
const t = ((r = this.rrwebCapturer) == null ? void 0 : r.getDroppedEventsCount()) ?? 0, e = (this.options.maxStorageMb ?? 50) * 1024 * 1024;
|
|
5360
5381
|
return {
|
|
5361
5382
|
state: this.stateMachine.getState(),
|
|
5362
5383
|
droppedEvents: t,
|
|
@@ -5367,7 +5388,7 @@ const ft = "0.5.1", v = class v {
|
|
|
5367
5388
|
protectedStorageExceeded: this.cachedProtectedBytes > e,
|
|
5368
5389
|
browserStorageEstimateBytes: this.cachedBrowserEstimateBytes,
|
|
5369
5390
|
browserStorageQuotaBytes: this.cachedBrowserQuotaBytes,
|
|
5370
|
-
pendingWrites: ((
|
|
5391
|
+
pendingWrites: ((n = this.writer) == null ? void 0 : n.getPendingWrites()) ?? 0,
|
|
5371
5392
|
incidentCount: this.cachedIncidentCount,
|
|
5372
5393
|
reasons: this.stateMachine.getDegradedReasons()
|
|
5373
5394
|
};
|
|
@@ -5402,10 +5423,10 @@ export {
|
|
|
5402
5423
|
X as MAX_ARTIFACT_BYTES,
|
|
5403
5424
|
Zt as NavigationCapturer,
|
|
5404
5425
|
Qt as NetworkCapturer,
|
|
5405
|
-
|
|
5426
|
+
ne as PerformanceCapturer,
|
|
5406
5427
|
Mt as RecorderStateMachine,
|
|
5407
5428
|
Pt as RetentionEngine,
|
|
5408
|
-
|
|
5429
|
+
re as RrwebCapturer,
|
|
5409
5430
|
T as STORE_CHUNKS,
|
|
5410
5431
|
R as STORE_INCIDENTS,
|
|
5411
5432
|
O as STORE_SESSIONS,
|
|
@@ -5438,7 +5459,7 @@ export {
|
|
|
5438
5459
|
he as sliceReplayEventsForWindow,
|
|
5439
5460
|
yt as sliceReplayEventsWithMetadata,
|
|
5440
5461
|
Et as sortTimelineEvents,
|
|
5441
|
-
|
|
5462
|
+
gt as uploadArtifactToGist,
|
|
5442
5463
|
It as validateFlightRecorderArtifact
|
|
5443
5464
|
};
|
|
5444
5465
|
//# sourceMappingURL=index.js.map
|