@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
package/dist/adapters/nuxt.cjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkYPGRVKY4_cjs = require('../chunk-YPGRVKY4.cjs');
|
|
4
|
+
require('../chunk-M2E6CWGK.cjs');
|
|
5
5
|
|
|
6
6
|
// src/adapters/nuxt.ts
|
|
7
7
|
function createNuxtOffscript(config) {
|
|
8
8
|
if (typeof window === "undefined") return null;
|
|
9
|
-
const sdk = new
|
|
9
|
+
const sdk = new chunkYPGRVKY4_cjs.Offscript(config);
|
|
10
10
|
void sdk.init().catch(() => void 0);
|
|
11
11
|
return sdk;
|
|
12
12
|
}
|
package/dist/adapters/nuxt.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
3
|
+
var chunkWK242AJ2_cjs = require('../chunk-WK242AJ2.cjs');
|
|
4
|
+
require('../chunk-YPGRVKY4.cjs');
|
|
5
|
+
require('../chunk-M2E6CWGK.cjs');
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
Object.defineProperty(exports, "createOffscript", {
|
|
10
10
|
enumerable: true,
|
|
11
|
-
get: function () { return
|
|
11
|
+
get: function () { return chunkWK242AJ2_cjs.createOffscript; }
|
|
12
12
|
});
|
|
13
13
|
Object.defineProperty(exports, "startOffscript", {
|
|
14
14
|
enumerable: true,
|
|
15
|
-
get: function () { return
|
|
15
|
+
get: function () { return chunkWK242AJ2_cjs.startOffscript; }
|
|
16
16
|
});
|
|
17
17
|
//# sourceMappingURL=vanilla.cjs.map
|
|
18
18
|
//# sourceMappingURL=vanilla.cjs.map
|
package/dist/adapters/vanilla.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { createOffscript, startOffscript } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { createOffscript, startOffscript } from '../chunk-U232L3JD.js';
|
|
2
|
+
import '../chunk-5F637PDG.js';
|
|
3
|
+
import '../chunk-KKEYBVTX.js';
|
|
4
4
|
//# sourceMappingURL=vanilla.js.map
|
|
5
5
|
//# sourceMappingURL=vanilla.js.map
|
package/dist/adapters/vue.cjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
3
|
+
var chunkYPGRVKY4_cjs = require('../chunk-YPGRVKY4.cjs');
|
|
4
|
+
require('../chunk-M2E6CWGK.cjs');
|
|
5
5
|
|
|
6
6
|
// src/adapters/vue.ts
|
|
7
7
|
var OFFSCRIPT_KEY = "$offscript";
|
|
8
8
|
var OffscriptPlugin = {
|
|
9
9
|
install(app, config) {
|
|
10
|
-
const sdk = new
|
|
10
|
+
const sdk = new chunkYPGRVKY4_cjs.Offscript(config);
|
|
11
11
|
void sdk.init().catch(() => void 0);
|
|
12
12
|
if (app.config?.globalProperties) {
|
|
13
13
|
app.config.globalProperties[OFFSCRIPT_KEY] = sdk;
|
package/dist/adapters/vue.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildPlaywrightContract, SDK_VERSION, SelectorGenerator, ACTION_SCHEMA_VERSION } from './chunk-
|
|
1
|
+
import { buildPlaywrightContract, SDK_VERSION, SelectorGenerator, ACTION_SCHEMA_VERSION } from './chunk-KKEYBVTX.js';
|
|
2
2
|
|
|
3
3
|
// src/types/config.ts
|
|
4
4
|
var DEFAULT_RECORDING = {
|
|
@@ -1253,6 +1253,8 @@ var IframeRecorder = class {
|
|
|
1253
1253
|
var PRIORITY = { 2: "critical", 4: "critical", 5: "critical", 0: "normal", 1: "normal", 3: "normal", 6: "normal" };
|
|
1254
1254
|
var URL_ATTRS = ["src", "href", "action", "poster", "data-src", "data", "formaction", "srcset", "cite", "rr_src"];
|
|
1255
1255
|
var LOW_SOURCES = /* @__PURE__ */ new Set([1, 6, 12, 3]);
|
|
1256
|
+
var SNAPSHOT_DEBOUNCE_MS = 200;
|
|
1257
|
+
var SNAPSHOT_SETTLE_TIMEOUT_MS = 5e3;
|
|
1256
1258
|
var RRWebRecorder = class {
|
|
1257
1259
|
constructor(sink) {
|
|
1258
1260
|
this.sink = sink;
|
|
@@ -1261,6 +1263,7 @@ var RRWebRecorder = class {
|
|
|
1261
1263
|
this.stopped = true;
|
|
1262
1264
|
this.needsSnapshot = false;
|
|
1263
1265
|
this.snapshotsTaken = 0;
|
|
1266
|
+
this.settling = false;
|
|
1264
1267
|
}
|
|
1265
1268
|
async start() {
|
|
1266
1269
|
this.stopped = false;
|
|
@@ -1293,14 +1296,76 @@ var RRWebRecorder = class {
|
|
|
1293
1296
|
};
|
|
1294
1297
|
this.stopFn = mod.record(options) ?? void 0;
|
|
1295
1298
|
}
|
|
1299
|
+
/** Captura o DOM depois do ciclo de renderização atual (Vue, React, etc.). */
|
|
1300
|
+
scheduleSnapshot() {
|
|
1301
|
+
this.cancelScheduledSnapshot();
|
|
1302
|
+
if (typeof window === "undefined") return;
|
|
1303
|
+
this.settling = true;
|
|
1304
|
+
if (typeof MutationObserver !== "undefined" && document.documentElement) {
|
|
1305
|
+
this.settleObserver = new MutationObserver(() => this.notifySnapshotActivity());
|
|
1306
|
+
this.settleObserver.observe(document.documentElement, {
|
|
1307
|
+
attributes: true,
|
|
1308
|
+
characterData: true,
|
|
1309
|
+
childList: true,
|
|
1310
|
+
subtree: true
|
|
1311
|
+
});
|
|
1312
|
+
}
|
|
1313
|
+
this.settleTimeout = window.setTimeout(() => this.captureSettledSnapshot(), SNAPSHOT_SETTLE_TIMEOUT_MS);
|
|
1314
|
+
}
|
|
1315
|
+
notifySnapshotActivity() {
|
|
1316
|
+
if (!this.settling || typeof window === "undefined") return;
|
|
1317
|
+
if (this.scheduledSnapshotTimer !== void 0) window.clearTimeout(this.scheduledSnapshotTimer);
|
|
1318
|
+
this.scheduledSnapshotTimer = window.setTimeout(() => this.captureSettledSnapshot(), SNAPSHOT_DEBOUNCE_MS);
|
|
1319
|
+
}
|
|
1320
|
+
captureSettledSnapshot() {
|
|
1321
|
+
if (!this.settling || typeof window === "undefined") return;
|
|
1322
|
+
this.settling = false;
|
|
1323
|
+
this.cancelScheduledSnapshot();
|
|
1324
|
+
const capture = () => {
|
|
1325
|
+
if (!this.stopped && !this.paused) this.takeFullSnapshot();
|
|
1326
|
+
};
|
|
1327
|
+
if (typeof window.requestAnimationFrame !== "function") {
|
|
1328
|
+
capture();
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
this.scheduledSnapshotFrame = window.requestAnimationFrame(() => {
|
|
1332
|
+
this.scheduledSnapshotFrame = window.requestAnimationFrame(() => {
|
|
1333
|
+
this.scheduledSnapshotFrame = void 0;
|
|
1334
|
+
capture();
|
|
1335
|
+
});
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
cancelScheduledSnapshot() {
|
|
1339
|
+
if (typeof window === "undefined") return;
|
|
1340
|
+
this.settling = false;
|
|
1341
|
+
if (this.scheduledSnapshotFrame !== void 0) {
|
|
1342
|
+
window.cancelAnimationFrame(this.scheduledSnapshotFrame);
|
|
1343
|
+
this.scheduledSnapshotFrame = void 0;
|
|
1344
|
+
}
|
|
1345
|
+
if (this.scheduledSnapshotTimer !== void 0) {
|
|
1346
|
+
window.clearTimeout(this.scheduledSnapshotTimer);
|
|
1347
|
+
this.scheduledSnapshotTimer = void 0;
|
|
1348
|
+
}
|
|
1349
|
+
if (this.settleTimeout !== void 0) {
|
|
1350
|
+
window.clearTimeout(this.settleTimeout);
|
|
1351
|
+
this.settleTimeout = void 0;
|
|
1352
|
+
}
|
|
1353
|
+
this.settleObserver?.disconnect();
|
|
1354
|
+
this.settleObserver = void 0;
|
|
1355
|
+
}
|
|
1296
1356
|
onEvent(event) {
|
|
1297
1357
|
if (this.paused) return;
|
|
1298
1358
|
guard(this.sink, this.name, () => {
|
|
1299
1359
|
this.sanitizeEvent(event);
|
|
1300
1360
|
let priority = PRIORITY[event.type] ?? "normal";
|
|
1301
1361
|
if (event.type === 3 && LOW_SOURCES.has(event.data?.source)) priority = "low";
|
|
1302
|
-
if (event.type === 2) this.snapshotsTaken++;
|
|
1303
1362
|
const emitted = this.sink.emit("rrweb", event, { priority, at: event.timestamp });
|
|
1363
|
+
if (event.type === 2) {
|
|
1364
|
+
this.needsSnapshot = !emitted;
|
|
1365
|
+
if (emitted) {
|
|
1366
|
+
this.snapshotsTaken++;
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1304
1369
|
if (!emitted && event.type === 3) this.needsSnapshot = true;
|
|
1305
1370
|
});
|
|
1306
1371
|
}
|
|
@@ -1333,13 +1398,15 @@ var RRWebRecorder = class {
|
|
|
1333
1398
|
/** Chamado pelo núcleo quando há folga novamente após descartes. */
|
|
1334
1399
|
recoverIfNeeded() {
|
|
1335
1400
|
if (this.needsSnapshot && !this.paused) {
|
|
1336
|
-
this.needsSnapshot = false;
|
|
1337
1401
|
this.takeFullSnapshot();
|
|
1338
1402
|
}
|
|
1339
1403
|
}
|
|
1340
1404
|
takeFullSnapshot() {
|
|
1341
1405
|
if (this.stopped) return;
|
|
1342
|
-
guard(this.sink, this.name, () =>
|
|
1406
|
+
guard(this.sink, this.name, () => {
|
|
1407
|
+
if (!this.mod?.record) return;
|
|
1408
|
+
this.mod.record.takeFullSnapshot(true);
|
|
1409
|
+
});
|
|
1343
1410
|
}
|
|
1344
1411
|
addCustomEvent(tag, payload) {
|
|
1345
1412
|
if (this.stopped) return;
|
|
@@ -1350,6 +1417,7 @@ var RRWebRecorder = class {
|
|
|
1350
1417
|
}
|
|
1351
1418
|
pause() {
|
|
1352
1419
|
this.paused = true;
|
|
1420
|
+
this.cancelScheduledSnapshot();
|
|
1353
1421
|
}
|
|
1354
1422
|
/** Ao retomar, as mutações perdidas durante a pausa exigem um snapshot completo. */
|
|
1355
1423
|
resume() {
|
|
@@ -1357,7 +1425,10 @@ var RRWebRecorder = class {
|
|
|
1357
1425
|
this.takeFullSnapshot();
|
|
1358
1426
|
}
|
|
1359
1427
|
stop() {
|
|
1428
|
+
const snapshotPending = this.settling || this.scheduledSnapshotFrame !== void 0;
|
|
1429
|
+
if (!this.stopped && !this.paused && snapshotPending) this.takeFullSnapshot();
|
|
1360
1430
|
this.stopped = true;
|
|
1431
|
+
this.cancelScheduledSnapshot();
|
|
1361
1432
|
safe(() => this.stopFn?.());
|
|
1362
1433
|
this.stopFn = void 0;
|
|
1363
1434
|
}
|
|
@@ -2213,7 +2284,7 @@ var SUCCESS_TEMPLATE = `
|
|
|
2213
2284
|
var TOKEN_STORAGE_KEY = "offscript-session-token";
|
|
2214
2285
|
var DRAFT_STORAGE_KEY = "offscript-draft-key";
|
|
2215
2286
|
var COMPLETED_TOKEN_STORAGE_KEY = "offscript-completed-token";
|
|
2216
|
-
var
|
|
2287
|
+
var NAVIGATION_SETTLE_WINDOW_MS = 5e3;
|
|
2217
2288
|
function tokenFingerprint(token) {
|
|
2218
2289
|
let first = 2166136261;
|
|
2219
2290
|
let second = 2654435769;
|
|
@@ -2224,6 +2295,23 @@ function tokenFingerprint(token) {
|
|
|
2224
2295
|
}
|
|
2225
2296
|
return `${first >>> 0}.${second >>> 0}`;
|
|
2226
2297
|
}
|
|
2298
|
+
async function encodeRecordingPayload(payload) {
|
|
2299
|
+
const json = JSON.stringify(payload);
|
|
2300
|
+
const CompressionStreamCtor = globalThis.CompressionStream;
|
|
2301
|
+
if (!CompressionStreamCtor) return { body: json };
|
|
2302
|
+
try {
|
|
2303
|
+
const stream = new CompressionStreamCtor("gzip");
|
|
2304
|
+
const writer = stream.writable.getWriter();
|
|
2305
|
+
await writer.write(new TextEncoder().encode(json));
|
|
2306
|
+
await writer.close();
|
|
2307
|
+
return {
|
|
2308
|
+
body: await new Response(stream.readable).blob(),
|
|
2309
|
+
contentEncoding: "gzip"
|
|
2310
|
+
};
|
|
2311
|
+
} catch {
|
|
2312
|
+
return { body: json };
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2227
2315
|
var Offscript = class {
|
|
2228
2316
|
constructor(config = {}) {
|
|
2229
2317
|
this.bus = new Emitter();
|
|
@@ -2240,6 +2328,7 @@ var Offscript = class {
|
|
|
2240
2328
|
this.pageId = uid("page_");
|
|
2241
2329
|
this.submitted = false;
|
|
2242
2330
|
this.launchTokenChanged = false;
|
|
2331
|
+
this.snapshotAfterNavigationUntil = 0;
|
|
2243
2332
|
this.config = resolveConfig(config);
|
|
2244
2333
|
this.sanitizer = new DataSanitizer(this.config.privacy);
|
|
2245
2334
|
}
|
|
@@ -2255,11 +2344,19 @@ var Offscript = class {
|
|
|
2255
2344
|
this.initPromise ?? (this.initPromise = this.initialize());
|
|
2256
2345
|
await this.initPromise;
|
|
2257
2346
|
if (this.restorePromise) await this.restorePromise;
|
|
2258
|
-
|
|
2347
|
+
this.exposeRunnerBridge();
|
|
2348
|
+
if (this.config.controls && this.launchToken && !this.controls && !window.__offscriptRunner?.enabled) {
|
|
2259
2349
|
this.controls = new RecordingControls(this);
|
|
2260
2350
|
this.controls.mount();
|
|
2261
2351
|
}
|
|
2262
2352
|
}
|
|
2353
|
+
exposeRunnerBridge() {
|
|
2354
|
+
const bridge = window.__offscriptRunner;
|
|
2355
|
+
if (!bridge?.enabled || !bridge.endpoint) return;
|
|
2356
|
+
bridge.startRecording = () => this.startRecording();
|
|
2357
|
+
bridge.complete = () => this.complete({ endpoint: bridge.endpoint });
|
|
2358
|
+
bridge.ready = true;
|
|
2359
|
+
}
|
|
2263
2360
|
async initialize() {
|
|
2264
2361
|
this.resolveLaunchToken();
|
|
2265
2362
|
if (this.launchToken && !this.config.persistenceKey) {
|
|
@@ -2315,27 +2412,8 @@ var Offscript = class {
|
|
|
2315
2412
|
async initializeDraft() {
|
|
2316
2413
|
if (!this.config.persistenceKey) return;
|
|
2317
2414
|
this.store = await RecordingStore.open(this.config.persistenceKey);
|
|
2318
|
-
|
|
2319
|
-
if (this.launchTokenChanged || startsNewSegment) await this.store.clear();
|
|
2415
|
+
if (this.launchTokenChanged) await this.store.clear();
|
|
2320
2416
|
await this.restoreDraft();
|
|
2321
|
-
if (startsNewSegment) await this.startFreshRecording();
|
|
2322
|
-
}
|
|
2323
|
-
async consumeRecordingSegmentMarker() {
|
|
2324
|
-
const url = new URL(window.location.href);
|
|
2325
|
-
const marker = url.searchParams.get(RECORDING_SEGMENT_START_QUERY);
|
|
2326
|
-
if (!marker) return false;
|
|
2327
|
-
url.searchParams.delete(RECORDING_SEGMENT_START_QUERY);
|
|
2328
|
-
window.history.replaceState(window.history.state, "", url.href);
|
|
2329
|
-
if (!this.launchToken || !globalThis.crypto?.subtle) return false;
|
|
2330
|
-
let fingerprint;
|
|
2331
|
-
try {
|
|
2332
|
-
const tokenBytes = new TextEncoder().encode(this.launchToken);
|
|
2333
|
-
const digest = await globalThis.crypto.subtle.digest("SHA-256", tokenBytes);
|
|
2334
|
-
fingerprint = Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
2335
|
-
} catch {
|
|
2336
|
-
return false;
|
|
2337
|
-
}
|
|
2338
|
-
return marker === fingerprint;
|
|
2339
2417
|
}
|
|
2340
2418
|
async restoreDraft() {
|
|
2341
2419
|
const saved = await this.store.load();
|
|
@@ -2465,10 +2543,17 @@ var Offscript = class {
|
|
|
2465
2543
|
if (!["https:", "http:"].includes(url.protocol)) throw new ConfigError("Endpoint HTTP inv\xE1lido");
|
|
2466
2544
|
const payload = await this.stopRecording();
|
|
2467
2545
|
try {
|
|
2546
|
+
const encodedPayload = await encodeRecordingPayload(payload);
|
|
2547
|
+
const headers = {
|
|
2548
|
+
"Content-Type": "application/json",
|
|
2549
|
+
Accept: "application/json",
|
|
2550
|
+
Authorization: `Bearer ${token}`
|
|
2551
|
+
};
|
|
2552
|
+
if (encodedPayload.contentEncoding) headers["Content-Encoding"] = encodedPayload.contentEncoding;
|
|
2468
2553
|
const response = await fetch(url.href, {
|
|
2469
2554
|
method: "POST",
|
|
2470
|
-
headers
|
|
2471
|
-
body:
|
|
2555
|
+
headers,
|
|
2556
|
+
body: encodedPayload.body
|
|
2472
2557
|
});
|
|
2473
2558
|
if (!response.ok) throw new OffscriptError("TRANSPORT_FAILED", `Falha ao enviar grava\xE7\xE3o: HTTP ${response.status}`, { status: response.status });
|
|
2474
2559
|
this.submitted = true;
|
|
@@ -2549,6 +2634,7 @@ var Offscript = class {
|
|
|
2549
2634
|
this.rrweb?.recoverIfNeeded();
|
|
2550
2635
|
const sequence = ++this.sequence;
|
|
2551
2636
|
const timestamp = opts.at ?? Date.now();
|
|
2637
|
+
if (kind === "http" && timestamp <= this.snapshotAfterNavigationUntil) this.rrweb?.notifySnapshotActivity();
|
|
2552
2638
|
const id = `${this.pageId}:${sequence}`;
|
|
2553
2639
|
let payload = data;
|
|
2554
2640
|
if (kind === "action") {
|
|
@@ -2615,6 +2701,8 @@ var Offscript = class {
|
|
|
2615
2701
|
this.actions?.recordNavigation(from, to, kind);
|
|
2616
2702
|
this.emitLifecycle("navigation", { from: this.sanitizer.sanitizeUrl(from), to: this.sanitizer.sanitizeUrl(to), kind }, "critical");
|
|
2617
2703
|
this.context?.record("navigation");
|
|
2704
|
+
this.snapshotAfterNavigationUntil = Date.now() + NAVIGATION_SETTLE_WINDOW_MS;
|
|
2705
|
+
this.rrweb?.scheduleSnapshot();
|
|
2618
2706
|
}
|
|
2619
2707
|
}));
|
|
2620
2708
|
this.lifecycle.install();
|
|
@@ -2675,5 +2763,5 @@ var Offscript = class {
|
|
|
2675
2763
|
Offscript.version = SDK_VERSION;
|
|
2676
2764
|
|
|
2677
2765
|
export { ConfigError, DEFAULT_PRIVACY, DEFAULT_RECORDING, DataSanitizer, InvalidStateError, Offscript, OffscriptError };
|
|
2678
|
-
//# sourceMappingURL=chunk-
|
|
2679
|
-
//# sourceMappingURL=chunk-
|
|
2766
|
+
//# sourceMappingURL=chunk-5F637PDG.js.map
|
|
2767
|
+
//# sourceMappingURL=chunk-5F637PDG.js.map
|