@offscript/sdk 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/nuxt.cjs +3 -3
- package/dist/adapters/nuxt.js +2 -2
- package/dist/adapters/vanilla.cjs +5 -5
- package/dist/adapters/vanilla.js +3 -3
- package/dist/adapters/vue.cjs +3 -3
- package/dist/adapters/vue.js +2 -2
- package/dist/{chunk-LUTOFXSV.js → chunk-5F637PDG.js} +118 -30
- package/dist/chunk-5F637PDG.js.map +1 -0
- package/dist/{chunk-4EPIPNDL.js → chunk-KKEYBVTX.js} +3 -3
- package/dist/{chunk-4EPIPNDL.js.map → chunk-KKEYBVTX.js.map} +1 -1
- package/dist/{chunk-M7CHVDW6.cjs → chunk-M2E6CWGK.cjs} +3 -3
- package/dist/{chunk-M7CHVDW6.cjs.map → chunk-M2E6CWGK.cjs.map} +1 -1
- package/dist/{chunk-ZB5N4KJE.js → chunk-U232L3JD.js} +3 -3
- package/dist/{chunk-ZB5N4KJE.js.map → chunk-U232L3JD.js.map} +1 -1
- package/dist/{chunk-OXGIMYKL.cjs → chunk-WK242AJ2.cjs} +4 -4
- package/dist/{chunk-OXGIMYKL.cjs.map → chunk-WK242AJ2.cjs.map} +1 -1
- package/dist/{chunk-7FCA5EJI.cjs → chunk-YPGRVKY4.cjs} +123 -35
- package/dist/chunk-YPGRVKY4.cjs.map +1 -0
- package/dist/core/OffscriptSDK.d.ts +16 -2
- package/dist/index.cjs +20 -20
- package/dist/index.js +3 -3
- package/dist/playwright.cjs +13 -13
- package/dist/playwright.js +1 -1
- package/dist/recorders/RRWebRecorder.d.ts +10 -0
- package/dist/types/events.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunk-7FCA5EJI.cjs.map +0 -1
- package/dist/chunk-LUTOFXSV.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkM2E6CWGK_cjs = require('./chunk-M2E6CWGK.cjs');
|
|
4
4
|
|
|
5
5
|
// src/types/config.ts
|
|
6
6
|
var DEFAULT_RECORDING = {
|
|
@@ -347,7 +347,7 @@ var ActionRecorder = class {
|
|
|
347
347
|
this.scrollState = /* @__PURE__ */ new Map();
|
|
348
348
|
this.move = [];
|
|
349
349
|
const r = sink.config.recording;
|
|
350
|
-
this.gen = new
|
|
350
|
+
this.gen = new chunkM2E6CWGK_cjs.SelectorGenerator({ testIdAttributes: r.testIdAttributes, stableAttributes: r.stableAttributes });
|
|
351
351
|
}
|
|
352
352
|
start() {
|
|
353
353
|
const d = this.d;
|
|
@@ -411,7 +411,7 @@ var ActionRecorder = class {
|
|
|
411
411
|
emit(draft, el, extra) {
|
|
412
412
|
const s = this.sink.sanitizer;
|
|
413
413
|
const data = {
|
|
414
|
-
schemaVersion:
|
|
414
|
+
schemaVersion: chunkM2E6CWGK_cjs.ACTION_SCHEMA_VERSION,
|
|
415
415
|
type: draft.type,
|
|
416
416
|
url: s.sanitizeUrl(location.href),
|
|
417
417
|
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
@@ -672,7 +672,7 @@ function collectContext(reason, captureSensitiveValues = false) {
|
|
|
672
672
|
timezone: safe(() => Intl.DateTimeFormat().resolvedOptions().timeZone),
|
|
673
673
|
online: nav.onLine,
|
|
674
674
|
visibility: document.visibilityState,
|
|
675
|
-
sdkVersion:
|
|
675
|
+
sdkVersion: chunkM2E6CWGK_cjs.SDK_VERSION,
|
|
676
676
|
captureSensitiveValues
|
|
677
677
|
};
|
|
678
678
|
}
|
|
@@ -1255,6 +1255,8 @@ var IframeRecorder = class {
|
|
|
1255
1255
|
var PRIORITY = { 2: "critical", 4: "critical", 5: "critical", 0: "normal", 1: "normal", 3: "normal", 6: "normal" };
|
|
1256
1256
|
var URL_ATTRS = ["src", "href", "action", "poster", "data-src", "data", "formaction", "srcset", "cite", "rr_src"];
|
|
1257
1257
|
var LOW_SOURCES = /* @__PURE__ */ new Set([1, 6, 12, 3]);
|
|
1258
|
+
var SNAPSHOT_DEBOUNCE_MS = 200;
|
|
1259
|
+
var SNAPSHOT_SETTLE_TIMEOUT_MS = 5e3;
|
|
1258
1260
|
var RRWebRecorder = class {
|
|
1259
1261
|
constructor(sink) {
|
|
1260
1262
|
this.sink = sink;
|
|
@@ -1263,6 +1265,7 @@ var RRWebRecorder = class {
|
|
|
1263
1265
|
this.stopped = true;
|
|
1264
1266
|
this.needsSnapshot = false;
|
|
1265
1267
|
this.snapshotsTaken = 0;
|
|
1268
|
+
this.settling = false;
|
|
1266
1269
|
}
|
|
1267
1270
|
async start() {
|
|
1268
1271
|
this.stopped = false;
|
|
@@ -1295,14 +1298,76 @@ var RRWebRecorder = class {
|
|
|
1295
1298
|
};
|
|
1296
1299
|
this.stopFn = mod.record(options) ?? void 0;
|
|
1297
1300
|
}
|
|
1301
|
+
/** Captura o DOM depois do ciclo de renderização atual (Vue, React, etc.). */
|
|
1302
|
+
scheduleSnapshot() {
|
|
1303
|
+
this.cancelScheduledSnapshot();
|
|
1304
|
+
if (typeof window === "undefined") return;
|
|
1305
|
+
this.settling = true;
|
|
1306
|
+
if (typeof MutationObserver !== "undefined" && document.documentElement) {
|
|
1307
|
+
this.settleObserver = new MutationObserver(() => this.notifySnapshotActivity());
|
|
1308
|
+
this.settleObserver.observe(document.documentElement, {
|
|
1309
|
+
attributes: true,
|
|
1310
|
+
characterData: true,
|
|
1311
|
+
childList: true,
|
|
1312
|
+
subtree: true
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
this.settleTimeout = window.setTimeout(() => this.captureSettledSnapshot(), SNAPSHOT_SETTLE_TIMEOUT_MS);
|
|
1316
|
+
}
|
|
1317
|
+
notifySnapshotActivity() {
|
|
1318
|
+
if (!this.settling || typeof window === "undefined") return;
|
|
1319
|
+
if (this.scheduledSnapshotTimer !== void 0) window.clearTimeout(this.scheduledSnapshotTimer);
|
|
1320
|
+
this.scheduledSnapshotTimer = window.setTimeout(() => this.captureSettledSnapshot(), SNAPSHOT_DEBOUNCE_MS);
|
|
1321
|
+
}
|
|
1322
|
+
captureSettledSnapshot() {
|
|
1323
|
+
if (!this.settling || typeof window === "undefined") return;
|
|
1324
|
+
this.settling = false;
|
|
1325
|
+
this.cancelScheduledSnapshot();
|
|
1326
|
+
const capture = () => {
|
|
1327
|
+
if (!this.stopped && !this.paused) this.takeFullSnapshot();
|
|
1328
|
+
};
|
|
1329
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
1330
|
+
capture();
|
|
1331
|
+
return;
|
|
1332
|
+
}
|
|
1333
|
+
this.scheduledSnapshotFrame = window.requestAnimationFrame(() => {
|
|
1334
|
+
this.scheduledSnapshotFrame = window.requestAnimationFrame(() => {
|
|
1335
|
+
this.scheduledSnapshotFrame = void 0;
|
|
1336
|
+
capture();
|
|
1337
|
+
});
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
cancelScheduledSnapshot() {
|
|
1341
|
+
if (typeof window === "undefined") return;
|
|
1342
|
+
this.settling = false;
|
|
1343
|
+
if (this.scheduledSnapshotFrame !== void 0) {
|
|
1344
|
+
window.cancelAnimationFrame(this.scheduledSnapshotFrame);
|
|
1345
|
+
this.scheduledSnapshotFrame = void 0;
|
|
1346
|
+
}
|
|
1347
|
+
if (this.scheduledSnapshotTimer !== void 0) {
|
|
1348
|
+
window.clearTimeout(this.scheduledSnapshotTimer);
|
|
1349
|
+
this.scheduledSnapshotTimer = void 0;
|
|
1350
|
+
}
|
|
1351
|
+
if (this.settleTimeout !== void 0) {
|
|
1352
|
+
window.clearTimeout(this.settleTimeout);
|
|
1353
|
+
this.settleTimeout = void 0;
|
|
1354
|
+
}
|
|
1355
|
+
this.settleObserver?.disconnect();
|
|
1356
|
+
this.settleObserver = void 0;
|
|
1357
|
+
}
|
|
1298
1358
|
onEvent(event) {
|
|
1299
1359
|
if (this.paused) return;
|
|
1300
1360
|
guard(this.sink, this.name, () => {
|
|
1301
1361
|
this.sanitizeEvent(event);
|
|
1302
1362
|
let priority = PRIORITY[event.type] ?? "normal";
|
|
1303
1363
|
if (event.type === 3 && LOW_SOURCES.has(event.data?.source)) priority = "low";
|
|
1304
|
-
if (event.type === 2) this.snapshotsTaken++;
|
|
1305
1364
|
const emitted = this.sink.emit("rrweb", event, { priority, at: event.timestamp });
|
|
1365
|
+
if (event.type === 2) {
|
|
1366
|
+
this.needsSnapshot = !emitted;
|
|
1367
|
+
if (emitted) {
|
|
1368
|
+
this.snapshotsTaken++;
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1306
1371
|
if (!emitted && event.type === 3) this.needsSnapshot = true;
|
|
1307
1372
|
});
|
|
1308
1373
|
}
|
|
@@ -1335,13 +1400,15 @@ var RRWebRecorder = class {
|
|
|
1335
1400
|
/** Chamado pelo núcleo quando há folga novamente após descartes. */
|
|
1336
1401
|
recoverIfNeeded() {
|
|
1337
1402
|
if (this.needsSnapshot && !this.paused) {
|
|
1338
|
-
this.needsSnapshot = false;
|
|
1339
1403
|
this.takeFullSnapshot();
|
|
1340
1404
|
}
|
|
1341
1405
|
}
|
|
1342
1406
|
takeFullSnapshot() {
|
|
1343
1407
|
if (this.stopped) return;
|
|
1344
|
-
guard(this.sink, this.name, () =>
|
|
1408
|
+
guard(this.sink, this.name, () => {
|
|
1409
|
+
if (!this.mod?.record) return;
|
|
1410
|
+
this.mod.record.takeFullSnapshot(true);
|
|
1411
|
+
});
|
|
1345
1412
|
}
|
|
1346
1413
|
addCustomEvent(tag, payload) {
|
|
1347
1414
|
if (this.stopped) return;
|
|
@@ -1352,6 +1419,7 @@ var RRWebRecorder = class {
|
|
|
1352
1419
|
}
|
|
1353
1420
|
pause() {
|
|
1354
1421
|
this.paused = true;
|
|
1422
|
+
this.cancelScheduledSnapshot();
|
|
1355
1423
|
}
|
|
1356
1424
|
/** Ao retomar, as mutações perdidas durante a pausa exigem um snapshot completo. */
|
|
1357
1425
|
resume() {
|
|
@@ -1359,7 +1427,10 @@ var RRWebRecorder = class {
|
|
|
1359
1427
|
this.takeFullSnapshot();
|
|
1360
1428
|
}
|
|
1361
1429
|
stop() {
|
|
1430
|
+
const snapshotPending = this.settling || this.scheduledSnapshotFrame !== void 0;
|
|
1431
|
+
if (!this.stopped && !this.paused && snapshotPending) this.takeFullSnapshot();
|
|
1362
1432
|
this.stopped = true;
|
|
1433
|
+
this.cancelScheduledSnapshot();
|
|
1363
1434
|
safe(() => this.stopFn?.());
|
|
1364
1435
|
this.stopFn = void 0;
|
|
1365
1436
|
}
|
|
@@ -2215,7 +2286,7 @@ var SUCCESS_TEMPLATE = `
|
|
|
2215
2286
|
var TOKEN_STORAGE_KEY = "offscript-session-token";
|
|
2216
2287
|
var DRAFT_STORAGE_KEY = "offscript-draft-key";
|
|
2217
2288
|
var COMPLETED_TOKEN_STORAGE_KEY = "offscript-completed-token";
|
|
2218
|
-
var
|
|
2289
|
+
var NAVIGATION_SETTLE_WINDOW_MS = 5e3;
|
|
2219
2290
|
function tokenFingerprint(token) {
|
|
2220
2291
|
let first = 2166136261;
|
|
2221
2292
|
let second = 2654435769;
|
|
@@ -2226,6 +2297,23 @@ function tokenFingerprint(token) {
|
|
|
2226
2297
|
}
|
|
2227
2298
|
return `${first >>> 0}.${second >>> 0}`;
|
|
2228
2299
|
}
|
|
2300
|
+
async function encodeRecordingPayload(payload) {
|
|
2301
|
+
const json = JSON.stringify(payload);
|
|
2302
|
+
const CompressionStreamCtor = globalThis.CompressionStream;
|
|
2303
|
+
if (!CompressionStreamCtor) return { body: json };
|
|
2304
|
+
try {
|
|
2305
|
+
const stream = new CompressionStreamCtor("gzip");
|
|
2306
|
+
const writer = stream.writable.getWriter();
|
|
2307
|
+
await writer.write(new TextEncoder().encode(json));
|
|
2308
|
+
await writer.close();
|
|
2309
|
+
return {
|
|
2310
|
+
body: await new Response(stream.readable).blob(),
|
|
2311
|
+
contentEncoding: "gzip"
|
|
2312
|
+
};
|
|
2313
|
+
} catch {
|
|
2314
|
+
return { body: json };
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2229
2317
|
var Offscript = class {
|
|
2230
2318
|
constructor(config = {}) {
|
|
2231
2319
|
this.bus = new Emitter();
|
|
@@ -2242,6 +2330,7 @@ var Offscript = class {
|
|
|
2242
2330
|
this.pageId = uid("page_");
|
|
2243
2331
|
this.submitted = false;
|
|
2244
2332
|
this.launchTokenChanged = false;
|
|
2333
|
+
this.snapshotAfterNavigationUntil = 0;
|
|
2245
2334
|
this.config = resolveConfig(config);
|
|
2246
2335
|
this.sanitizer = new DataSanitizer(this.config.privacy);
|
|
2247
2336
|
}
|
|
@@ -2257,11 +2346,19 @@ var Offscript = class {
|
|
|
2257
2346
|
this.initPromise ?? (this.initPromise = this.initialize());
|
|
2258
2347
|
await this.initPromise;
|
|
2259
2348
|
if (this.restorePromise) await this.restorePromise;
|
|
2260
|
-
|
|
2349
|
+
this.exposeRunnerBridge();
|
|
2350
|
+
if (this.config.controls && this.launchToken && !this.controls && !window.__offscriptRunner?.enabled) {
|
|
2261
2351
|
this.controls = new RecordingControls(this);
|
|
2262
2352
|
this.controls.mount();
|
|
2263
2353
|
}
|
|
2264
2354
|
}
|
|
2355
|
+
exposeRunnerBridge() {
|
|
2356
|
+
const bridge = window.__offscriptRunner;
|
|
2357
|
+
if (!bridge?.enabled || !bridge.endpoint) return;
|
|
2358
|
+
bridge.startRecording = () => this.startRecording();
|
|
2359
|
+
bridge.complete = () => this.complete({ endpoint: bridge.endpoint });
|
|
2360
|
+
bridge.ready = true;
|
|
2361
|
+
}
|
|
2265
2362
|
async initialize() {
|
|
2266
2363
|
this.resolveLaunchToken();
|
|
2267
2364
|
if (this.launchToken && !this.config.persistenceKey) {
|
|
@@ -2317,27 +2414,8 @@ var Offscript = class {
|
|
|
2317
2414
|
async initializeDraft() {
|
|
2318
2415
|
if (!this.config.persistenceKey) return;
|
|
2319
2416
|
this.store = await RecordingStore.open(this.config.persistenceKey);
|
|
2320
|
-
|
|
2321
|
-
if (this.launchTokenChanged || startsNewSegment) await this.store.clear();
|
|
2417
|
+
if (this.launchTokenChanged) await this.store.clear();
|
|
2322
2418
|
await this.restoreDraft();
|
|
2323
|
-
if (startsNewSegment) await this.startFreshRecording();
|
|
2324
|
-
}
|
|
2325
|
-
async consumeRecordingSegmentMarker() {
|
|
2326
|
-
const url = new URL(window.location.href);
|
|
2327
|
-
const marker = url.searchParams.get(RECORDING_SEGMENT_START_QUERY);
|
|
2328
|
-
if (!marker) return false;
|
|
2329
|
-
url.searchParams.delete(RECORDING_SEGMENT_START_QUERY);
|
|
2330
|
-
window.history.replaceState(window.history.state, "", url.href);
|
|
2331
|
-
if (!this.launchToken || !globalThis.crypto?.subtle) return false;
|
|
2332
|
-
let fingerprint;
|
|
2333
|
-
try {
|
|
2334
|
-
const tokenBytes = new TextEncoder().encode(this.launchToken);
|
|
2335
|
-
const digest = await globalThis.crypto.subtle.digest("SHA-256", tokenBytes);
|
|
2336
|
-
fingerprint = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2337
|
-
} catch {
|
|
2338
|
-
return false;
|
|
2339
|
-
}
|
|
2340
|
-
return marker === fingerprint;
|
|
2341
2419
|
}
|
|
2342
2420
|
async restoreDraft() {
|
|
2343
2421
|
const saved = await this.store.load();
|
|
@@ -2467,10 +2545,17 @@ var Offscript = class {
|
|
|
2467
2545
|
if (!["https:", "http:"].includes(url.protocol)) throw new ConfigError("Endpoint HTTP inv\xE1lido");
|
|
2468
2546
|
const payload = await this.stopRecording();
|
|
2469
2547
|
try {
|
|
2548
|
+
const encodedPayload = await encodeRecordingPayload(payload);
|
|
2549
|
+
const headers = {
|
|
2550
|
+
"Content-Type": "application/json",
|
|
2551
|
+
Accept: "application/json",
|
|
2552
|
+
Authorization: `Bearer ${token}`
|
|
2553
|
+
};
|
|
2554
|
+
if (encodedPayload.contentEncoding) headers["Content-Encoding"] = encodedPayload.contentEncoding;
|
|
2470
2555
|
const response = await fetch(url.href, {
|
|
2471
2556
|
method: "POST",
|
|
2472
|
-
headers
|
|
2473
|
-
body:
|
|
2557
|
+
headers,
|
|
2558
|
+
body: encodedPayload.body
|
|
2474
2559
|
});
|
|
2475
2560
|
if (!response.ok) throw new OffscriptError("TRANSPORT_FAILED", `Falha ao enviar grava\xE7\xE3o: HTTP ${response.status}`, { status: response.status });
|
|
2476
2561
|
this.submitted = true;
|
|
@@ -2532,7 +2617,7 @@ var Offscript = class {
|
|
|
2532
2617
|
this.destroyed = true;
|
|
2533
2618
|
}
|
|
2534
2619
|
exportPlaywrightData() {
|
|
2535
|
-
return
|
|
2620
|
+
return chunkM2E6CWGK_cjs.buildPlaywrightContract({ actions: this.actionLog, contexts: this.contextLog });
|
|
2536
2621
|
}
|
|
2537
2622
|
getRecordedActions() {
|
|
2538
2623
|
return this.actionLog;
|
|
@@ -2551,6 +2636,7 @@ var Offscript = class {
|
|
|
2551
2636
|
this.rrweb?.recoverIfNeeded();
|
|
2552
2637
|
const sequence = ++this.sequence;
|
|
2553
2638
|
const timestamp = opts.at ?? Date.now();
|
|
2639
|
+
if (kind === "http" && timestamp <= this.snapshotAfterNavigationUntil) this.rrweb?.notifySnapshotActivity();
|
|
2554
2640
|
const id = `${this.pageId}:${sequence}`;
|
|
2555
2641
|
let payload = data;
|
|
2556
2642
|
if (kind === "action") {
|
|
@@ -2617,6 +2703,8 @@ var Offscript = class {
|
|
|
2617
2703
|
this.actions?.recordNavigation(from, to, kind);
|
|
2618
2704
|
this.emitLifecycle("navigation", { from: this.sanitizer.sanitizeUrl(from), to: this.sanitizer.sanitizeUrl(to), kind }, "critical");
|
|
2619
2705
|
this.context?.record("navigation");
|
|
2706
|
+
this.snapshotAfterNavigationUntil = Date.now() + NAVIGATION_SETTLE_WINDOW_MS;
|
|
2707
|
+
this.rrweb?.scheduleSnapshot();
|
|
2620
2708
|
}
|
|
2621
2709
|
}));
|
|
2622
2710
|
this.lifecycle.install();
|
|
@@ -2674,7 +2762,7 @@ var Offscript = class {
|
|
|
2674
2762
|
this.bus.emit("statusChange", { from, to });
|
|
2675
2763
|
}
|
|
2676
2764
|
};
|
|
2677
|
-
Offscript.version =
|
|
2765
|
+
Offscript.version = chunkM2E6CWGK_cjs.SDK_VERSION;
|
|
2678
2766
|
|
|
2679
2767
|
exports.ConfigError = ConfigError;
|
|
2680
2768
|
exports.DEFAULT_PRIVACY = DEFAULT_PRIVACY;
|
|
@@ -2683,5 +2771,5 @@ exports.DataSanitizer = DataSanitizer;
|
|
|
2683
2771
|
exports.InvalidStateError = InvalidStateError;
|
|
2684
2772
|
exports.Offscript = Offscript;
|
|
2685
2773
|
exports.OffscriptError = OffscriptError;
|
|
2686
|
-
//# sourceMappingURL=chunk-
|
|
2687
|
-
//# sourceMappingURL=chunk-
|
|
2774
|
+
//# sourceMappingURL=chunk-YPGRVKY4.cjs.map
|
|
2775
|
+
//# sourceMappingURL=chunk-YPGRVKY4.cjs.map
|