@offscript/sdk 0.1.5 → 0.1.7
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 +10 -20
- 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-6ROP37WI.js → chunk-4EPIPNDL.js} +3 -3
- package/dist/{chunk-6ROP37WI.js.map → chunk-4EPIPNDL.js.map} +1 -1
- package/dist/{chunk-VYCDQLP7.cjs → chunk-7FCA5EJI.cjs} +116 -14
- package/dist/chunk-7FCA5EJI.cjs.map +1 -0
- package/dist/{chunk-XBXFGCUT.js → chunk-LUTOFXSV.js} +111 -9
- package/dist/chunk-LUTOFXSV.js.map +1 -0
- package/dist/{chunk-HPDLEAAL.cjs → chunk-M7CHVDW6.cjs} +3 -3
- package/dist/{chunk-HPDLEAAL.cjs.map → chunk-M7CHVDW6.cjs.map} +1 -1
- package/dist/{chunk-2MY2FWIA.cjs → chunk-OXGIMYKL.cjs} +4 -4
- package/dist/{chunk-2MY2FWIA.cjs.map → chunk-OXGIMYKL.cjs.map} +1 -1
- package/dist/{chunk-V2YYWGIA.js → chunk-ZB5N4KJE.js} +3 -3
- package/dist/{chunk-V2YYWGIA.js.map → chunk-ZB5N4KJE.js.map} +1 -1
- package/dist/core/OffscriptSDK.d.ts +12 -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/types/config.d.ts +5 -2
- package/dist/types/events.d.ts +1 -1
- package/dist/types/recording.d.ts +2 -2
- package/docs/api-contract.md +1 -1
- package/docs/architecture.md +3 -3
- package/package.json +2 -2
- package/dist/chunk-VYCDQLP7.cjs.map +0 -1
- package/dist/chunk-XBXFGCUT.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkM7CHVDW6_cjs = require('./chunk-M7CHVDW6.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 chunkM7CHVDW6_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: chunkM7CHVDW6_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: chunkM7CHVDW6_cjs.SDK_VERSION,
|
|
676
676
|
captureSensitiveValues
|
|
677
677
|
};
|
|
678
678
|
}
|
|
@@ -1533,6 +1533,7 @@ function resolveConfig(input) {
|
|
|
1533
1533
|
privacy: resolvePrivacy(input.privacy),
|
|
1534
1534
|
correlationWindowMs: input.correlationWindowMs ?? 3e3,
|
|
1535
1535
|
controls: input.controls ?? true,
|
|
1536
|
+
endpoint: input.endpoint,
|
|
1536
1537
|
persistenceKey: input.persistenceKey,
|
|
1537
1538
|
onComplete: input.onComplete
|
|
1538
1539
|
};
|
|
@@ -2211,6 +2212,20 @@ var SUCCESS_TEMPLATE = `
|
|
|
2211
2212
|
`;
|
|
2212
2213
|
|
|
2213
2214
|
// src/core/OffscriptSDK.ts
|
|
2215
|
+
var TOKEN_STORAGE_KEY = "offscript-session-token";
|
|
2216
|
+
var DRAFT_STORAGE_KEY = "offscript-draft-key";
|
|
2217
|
+
var COMPLETED_TOKEN_STORAGE_KEY = "offscript-completed-token";
|
|
2218
|
+
var RECORDING_SEGMENT_START_QUERY = "offscript_recording_start";
|
|
2219
|
+
function tokenFingerprint(token) {
|
|
2220
|
+
let first = 2166136261;
|
|
2221
|
+
let second = 2654435769;
|
|
2222
|
+
for (let index = 0; index < token.length; index++) {
|
|
2223
|
+
const character = token.charCodeAt(index);
|
|
2224
|
+
first = Math.imul(first ^ character, 16777619);
|
|
2225
|
+
second = Math.imul(second ^ character, 2246822519);
|
|
2226
|
+
}
|
|
2227
|
+
return `${first >>> 0}.${second >>> 0}`;
|
|
2228
|
+
}
|
|
2214
2229
|
var Offscript = class {
|
|
2215
2230
|
constructor(config = {}) {
|
|
2216
2231
|
this.bus = new Emitter();
|
|
@@ -2226,6 +2241,7 @@ var Offscript = class {
|
|
|
2226
2241
|
this.sequence = 0;
|
|
2227
2242
|
this.pageId = uid("page_");
|
|
2228
2243
|
this.submitted = false;
|
|
2244
|
+
this.launchTokenChanged = false;
|
|
2229
2245
|
this.config = resolveConfig(config);
|
|
2230
2246
|
this.sanitizer = new DataSanitizer(this.config.privacy);
|
|
2231
2247
|
}
|
|
@@ -2238,18 +2254,90 @@ var Offscript = class {
|
|
|
2238
2254
|
async init() {
|
|
2239
2255
|
this.assertAlive();
|
|
2240
2256
|
if (typeof window === "undefined") throw new OffscriptError("NOT_SUPPORTED", "O SDK requer um navegador");
|
|
2241
|
-
this.initPromise ?? (this.initPromise = this.
|
|
2257
|
+
this.initPromise ?? (this.initPromise = this.initialize());
|
|
2242
2258
|
await this.initPromise;
|
|
2243
2259
|
if (this.restorePromise) await this.restorePromise;
|
|
2244
|
-
if (this.config.controls && !this.controls) {
|
|
2260
|
+
if (this.config.controls && this.launchToken && !this.controls) {
|
|
2245
2261
|
this.controls = new RecordingControls(this);
|
|
2246
2262
|
this.controls.mount();
|
|
2247
2263
|
}
|
|
2248
2264
|
}
|
|
2265
|
+
async initialize() {
|
|
2266
|
+
this.resolveLaunchToken();
|
|
2267
|
+
if (this.launchToken && !this.config.persistenceKey) {
|
|
2268
|
+
this.config.persistenceKey = this.getOrCreateDraftKey();
|
|
2269
|
+
}
|
|
2270
|
+
await this.initializeDraft();
|
|
2271
|
+
}
|
|
2272
|
+
resolveLaunchToken() {
|
|
2273
|
+
const incomingToken = new URLSearchParams(window.location.search).get("offscript_token")?.trim();
|
|
2274
|
+
const previousToken = this.readSessionValue(TOKEN_STORAGE_KEY);
|
|
2275
|
+
const completedToken = this.readSessionValue(COMPLETED_TOKEN_STORAGE_KEY);
|
|
2276
|
+
const legacyCompletion = completedToken === "1" && Boolean(previousToken);
|
|
2277
|
+
const completedFingerprint = legacyCompletion && previousToken ? tokenFingerprint(previousToken) : completedToken;
|
|
2278
|
+
const candidateToken = incomingToken || previousToken || void 0;
|
|
2279
|
+
this.launchTokenChanged = Boolean(incomingToken && previousToken && incomingToken !== previousToken) || Boolean(incomingToken && completedFingerprint && completedFingerprint !== "1" && tokenFingerprint(incomingToken) !== completedFingerprint);
|
|
2280
|
+
if (this.launchTokenChanged) {
|
|
2281
|
+
this.removeSessionValue(COMPLETED_TOKEN_STORAGE_KEY);
|
|
2282
|
+
}
|
|
2283
|
+
if (legacyCompletion && previousToken && !this.launchTokenChanged) {
|
|
2284
|
+
this.writeSessionValue(COMPLETED_TOKEN_STORAGE_KEY, tokenFingerprint(previousToken));
|
|
2285
|
+
this.removeSessionValue(TOKEN_STORAGE_KEY);
|
|
2286
|
+
}
|
|
2287
|
+
const isCompleted = Boolean(candidateToken && completedFingerprint === tokenFingerprint(candidateToken));
|
|
2288
|
+
this.launchToken = isCompleted ? void 0 : candidateToken;
|
|
2289
|
+
if (incomingToken && !isCompleted) this.writeSessionValue(TOKEN_STORAGE_KEY, incomingToken);
|
|
2290
|
+
}
|
|
2291
|
+
getOrCreateDraftKey() {
|
|
2292
|
+
const saved = this.readSessionValue(DRAFT_STORAGE_KEY);
|
|
2293
|
+
if (saved) return saved;
|
|
2294
|
+
const key = uid("draft_");
|
|
2295
|
+
this.writeSessionValue(DRAFT_STORAGE_KEY, key);
|
|
2296
|
+
return key;
|
|
2297
|
+
}
|
|
2298
|
+
readSessionValue(key) {
|
|
2299
|
+
try {
|
|
2300
|
+
return window.sessionStorage.getItem(key);
|
|
2301
|
+
} catch {
|
|
2302
|
+
return null;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
writeSessionValue(key, value) {
|
|
2306
|
+
try {
|
|
2307
|
+
window.sessionStorage.setItem(key, value);
|
|
2308
|
+
} catch {
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
removeSessionValue(key) {
|
|
2312
|
+
try {
|
|
2313
|
+
window.sessionStorage.removeItem(key);
|
|
2314
|
+
} catch {
|
|
2315
|
+
}
|
|
2316
|
+
}
|
|
2249
2317
|
async initializeDraft() {
|
|
2250
2318
|
if (!this.config.persistenceKey) return;
|
|
2251
2319
|
this.store = await RecordingStore.open(this.config.persistenceKey);
|
|
2320
|
+
const startsNewSegment = await this.consumeRecordingSegmentMarker();
|
|
2321
|
+
if (this.launchTokenChanged || startsNewSegment) await this.store.clear();
|
|
2252
2322
|
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;
|
|
2253
2341
|
}
|
|
2254
2342
|
async restoreDraft() {
|
|
2255
2343
|
const saved = await this.store.load();
|
|
@@ -2289,6 +2377,9 @@ var Offscript = class {
|
|
|
2289
2377
|
}
|
|
2290
2378
|
async doStart() {
|
|
2291
2379
|
await this.init();
|
|
2380
|
+
await this.startFreshRecording();
|
|
2381
|
+
}
|
|
2382
|
+
async startFreshRecording() {
|
|
2292
2383
|
if (this.status === "recording" || this.status === "paused") return;
|
|
2293
2384
|
if (this.completePromise || this.stopPromise) throw new InvalidStateError("Finaliza\xE7\xE3o em andamento");
|
|
2294
2385
|
await this.store?.clear();
|
|
@@ -2358,7 +2449,7 @@ var Offscript = class {
|
|
|
2358
2449
|
this.bus.emit("recordingEnd", this.payload);
|
|
2359
2450
|
return this.payload;
|
|
2360
2451
|
}
|
|
2361
|
-
complete(options) {
|
|
2452
|
+
complete(options = {}) {
|
|
2362
2453
|
this.assertAlive();
|
|
2363
2454
|
if (this.completePromise) return this.completePromise;
|
|
2364
2455
|
if (this.submitted) return Promise.resolve(this.response);
|
|
@@ -2367,19 +2458,27 @@ var Offscript = class {
|
|
|
2367
2458
|
});
|
|
2368
2459
|
return this.completePromise;
|
|
2369
2460
|
}
|
|
2370
|
-
async doComplete(
|
|
2461
|
+
async doComplete(options) {
|
|
2462
|
+
const endpoint = options.endpoint ?? this.config.endpoint;
|
|
2463
|
+
const token = options.token?.trim() || this.launchToken;
|
|
2464
|
+
if (!endpoint) throw new ConfigError("Endpoint HTTP obrigat\xF3rio para envio");
|
|
2465
|
+
if (!token) throw new ConfigError("Token obrigat\xF3rio para envio");
|
|
2371
2466
|
const url = new URL(endpoint, location.href);
|
|
2372
2467
|
if (!["https:", "http:"].includes(url.protocol)) throw new ConfigError("Endpoint HTTP inv\xE1lido");
|
|
2373
|
-
if (!token?.trim()) throw new ConfigError("Token obrigat\xF3rio para envio");
|
|
2374
2468
|
const payload = await this.stopRecording();
|
|
2375
2469
|
try {
|
|
2376
2470
|
const response = await fetch(url.href, {
|
|
2377
2471
|
method: "POST",
|
|
2378
|
-
headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${token
|
|
2472
|
+
headers: { "Content-Type": "application/json", Accept: "application/json", Authorization: `Bearer ${token}` },
|
|
2379
2473
|
body: JSON.stringify(payload)
|
|
2380
2474
|
});
|
|
2381
2475
|
if (!response.ok) throw new OffscriptError("TRANSPORT_FAILED", `Falha ao enviar grava\xE7\xE3o: HTTP ${response.status}`, { status: response.status });
|
|
2382
2476
|
this.submitted = true;
|
|
2477
|
+
const completedToken = this.launchToken ?? token;
|
|
2478
|
+
this.writeSessionValue(COMPLETED_TOKEN_STORAGE_KEY, tokenFingerprint(completedToken));
|
|
2479
|
+
this.removeSessionValue(TOKEN_STORAGE_KEY);
|
|
2480
|
+
this.removeSessionValue(DRAFT_STORAGE_KEY);
|
|
2481
|
+
this.launchToken = void 0;
|
|
2383
2482
|
await this.store?.clear();
|
|
2384
2483
|
const text = await response.text();
|
|
2385
2484
|
try {
|
|
@@ -2389,6 +2488,8 @@ var Offscript = class {
|
|
|
2389
2488
|
}
|
|
2390
2489
|
this.lastError = void 0;
|
|
2391
2490
|
this.controls?.showSuccess();
|
|
2491
|
+
this.controls?.unmount();
|
|
2492
|
+
this.controls = void 0;
|
|
2392
2493
|
return this.response;
|
|
2393
2494
|
} catch (error) {
|
|
2394
2495
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -2399,6 +2500,7 @@ var Offscript = class {
|
|
|
2399
2500
|
}
|
|
2400
2501
|
async finishRecording() {
|
|
2401
2502
|
if (this.config.onComplete) return this.config.onComplete();
|
|
2503
|
+
if (this.launchToken) return this.complete();
|
|
2402
2504
|
return this.stopRecording();
|
|
2403
2505
|
}
|
|
2404
2506
|
async discardRecording() {
|
|
@@ -2430,7 +2532,7 @@ var Offscript = class {
|
|
|
2430
2532
|
this.destroyed = true;
|
|
2431
2533
|
}
|
|
2432
2534
|
exportPlaywrightData() {
|
|
2433
|
-
return
|
|
2535
|
+
return chunkM7CHVDW6_cjs.buildPlaywrightContract({ actions: this.actionLog, contexts: this.contextLog });
|
|
2434
2536
|
}
|
|
2435
2537
|
getRecordedActions() {
|
|
2436
2538
|
return this.actionLog;
|
|
@@ -2572,7 +2674,7 @@ var Offscript = class {
|
|
|
2572
2674
|
this.bus.emit("statusChange", { from, to });
|
|
2573
2675
|
}
|
|
2574
2676
|
};
|
|
2575
|
-
Offscript.version =
|
|
2677
|
+
Offscript.version = chunkM7CHVDW6_cjs.SDK_VERSION;
|
|
2576
2678
|
|
|
2577
2679
|
exports.ConfigError = ConfigError;
|
|
2578
2680
|
exports.DEFAULT_PRIVACY = DEFAULT_PRIVACY;
|
|
@@ -2581,5 +2683,5 @@ exports.DataSanitizer = DataSanitizer;
|
|
|
2581
2683
|
exports.InvalidStateError = InvalidStateError;
|
|
2582
2684
|
exports.Offscript = Offscript;
|
|
2583
2685
|
exports.OffscriptError = OffscriptError;
|
|
2584
|
-
//# sourceMappingURL=chunk-
|
|
2585
|
-
//# sourceMappingURL=chunk-
|
|
2686
|
+
//# sourceMappingURL=chunk-7FCA5EJI.cjs.map
|
|
2687
|
+
//# sourceMappingURL=chunk-7FCA5EJI.cjs.map
|