@cross-deck/web 1.6.4 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -49
- package/dist/contracts.json +12 -12
- package/dist/crossdeck.umd.min.js +2 -2
- package/dist/crossdeck.umd.min.js.map +1 -1
- package/dist/error-codes.json +1 -1
- package/dist/index.cjs +150 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +3 -4
- package/dist/index.d.ts +3 -4
- package/dist/index.mjs +150 -167
- package/dist/index.mjs.map +1 -1
- package/dist/react.cjs +139 -156
- package/dist/react.cjs.map +1 -1
- package/dist/react.mjs +139 -156
- package/dist/react.mjs.map +1 -1
- package/dist/vue.cjs +139 -156
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.mjs +139 -156
- package/dist/vue.mjs.map +1 -1
- package/package.json +1 -1
package/dist/vue.cjs
CHANGED
|
@@ -92,7 +92,7 @@ function typeMapForStatus(status) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// src/_version.ts
|
|
95
|
-
var SDK_VERSION = "1.
|
|
95
|
+
var SDK_VERSION = "1.7.0";
|
|
96
96
|
var SDK_NAME = "@cross-deck/web";
|
|
97
97
|
|
|
98
98
|
// src/http.ts
|
|
@@ -1008,9 +1008,13 @@ var EventQueue = class {
|
|
|
1008
1008
|
const env = this.cfg.envelope();
|
|
1009
1009
|
const result = await this.cfg.http.request("POST", "/events", {
|
|
1010
1010
|
body: {
|
|
1011
|
-
//
|
|
1012
|
-
//
|
|
1013
|
-
//
|
|
1011
|
+
// Event Envelope v1 batch envelope (backend/docs/
|
|
1012
|
+
// event-envelope-spec-v1.md §1). `envelopeVersion` is the
|
|
1013
|
+
// schema/wire version the server parses against ("can I parse
|
|
1014
|
+
// this?") and is DISTINCT from `sdk.version` ("which build is in
|
|
1015
|
+
// the wild?") — two questions, two fields, never conflated. The
|
|
1016
|
+
// backend refuses payloads with a missing/unknown envelopeVersion.
|
|
1017
|
+
envelopeVersion: 1,
|
|
1014
1018
|
appId: env.appId,
|
|
1015
1019
|
environment: env.environment,
|
|
1016
1020
|
sdk: env.sdk,
|
|
@@ -1465,6 +1469,15 @@ var AutoTracker = class {
|
|
|
1465
1469
|
this.cleanups = [];
|
|
1466
1470
|
/** Last time we flushed lastActivityAt to storage (throttle gate). */
|
|
1467
1471
|
this.lastPersistAt = 0;
|
|
1472
|
+
/**
|
|
1473
|
+
* Event Envelope v1 §3 — per-session monotonic sequence counter.
|
|
1474
|
+
* The single owner of the seq counter lives here, alongside all other
|
|
1475
|
+
* session state. Incremented atomically at track() time (via nextSeq()),
|
|
1476
|
+
* reset to 0 whenever a new session boundary is crossed (startNewSession
|
|
1477
|
+
* path + resetSession). Persists across background/foreground within a
|
|
1478
|
+
* session — only a real session boundary (not a tab hide/show) resets it.
|
|
1479
|
+
*/
|
|
1480
|
+
this._sessionSeq = 0;
|
|
1468
1481
|
/**
|
|
1469
1482
|
* Stable per-page-view identifier. Minted at every `page.viewed`
|
|
1470
1483
|
* emission and attached to every subsequent event until the next
|
|
@@ -1549,6 +1562,20 @@ var AutoTracker = class {
|
|
|
1549
1562
|
get currentAcquisition() {
|
|
1550
1563
|
return this.session?.acquisition ?? EMPTY_ACQUISITION;
|
|
1551
1564
|
}
|
|
1565
|
+
/**
|
|
1566
|
+
* Event Envelope v1 §3 — return the next seq value for the current session
|
|
1567
|
+
* and advance the counter. Called SYNCHRONOUSLY at track() time, before any
|
|
1568
|
+
* async dispatch, so the seq assignment order is deterministic (call order,
|
|
1569
|
+
* not scheduler luck). The counter is reset to 0 at every session boundary;
|
|
1570
|
+
* it is NOT reset by tab hide/show (spec §3 clause 1: backgrounding does not
|
|
1571
|
+
* reset seq). When no session is active (Node, before init, after uninstall),
|
|
1572
|
+
* returns 0 and leaves the counter unchanged — fallback, not an error.
|
|
1573
|
+
*/
|
|
1574
|
+
nextSeq() {
|
|
1575
|
+
const seq = this._sessionSeq;
|
|
1576
|
+
this._sessionSeq += 1;
|
|
1577
|
+
return seq;
|
|
1578
|
+
}
|
|
1552
1579
|
// ---------- sessions ----------
|
|
1553
1580
|
installSessionTracking() {
|
|
1554
1581
|
const now = Date.now();
|
|
@@ -1600,6 +1627,7 @@ var AutoTracker = class {
|
|
|
1600
1627
|
}
|
|
1601
1628
|
startNewSession() {
|
|
1602
1629
|
const now = Date.now();
|
|
1630
|
+
this._sessionSeq = 0;
|
|
1603
1631
|
return {
|
|
1604
1632
|
sessionId: mintSessionId(),
|
|
1605
1633
|
startedAt: now,
|
|
@@ -2328,6 +2356,40 @@ function writeJson(storage, key, value) {
|
|
|
2328
2356
|
}
|
|
2329
2357
|
}
|
|
2330
2358
|
|
|
2359
|
+
// src/internal-opt-out.ts
|
|
2360
|
+
var INTERNAL_OPT_OUT_PROPERTY = "$crossdeck_internal";
|
|
2361
|
+
var STORAGE_KEY = "crossdeck.internalOptOut";
|
|
2362
|
+
function localStore() {
|
|
2363
|
+
try {
|
|
2364
|
+
return typeof localStorage !== "undefined" ? localStorage : null;
|
|
2365
|
+
} catch {
|
|
2366
|
+
return null;
|
|
2367
|
+
}
|
|
2368
|
+
}
|
|
2369
|
+
function processInternalOptOutUrl() {
|
|
2370
|
+
try {
|
|
2371
|
+
const search = typeof location !== "undefined" ? location.search : "";
|
|
2372
|
+
const params = new URLSearchParams(search || "");
|
|
2373
|
+
if (!params.has("crossdeck_internal")) return;
|
|
2374
|
+
const store = localStore();
|
|
2375
|
+
if (!store) return;
|
|
2376
|
+
const v = params.get("crossdeck_internal");
|
|
2377
|
+
if (v === "1" || v === "true") {
|
|
2378
|
+
store.setItem(STORAGE_KEY, "1");
|
|
2379
|
+
} else if (v === "0" || v === "false") {
|
|
2380
|
+
store.removeItem(STORAGE_KEY);
|
|
2381
|
+
}
|
|
2382
|
+
} catch {
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
function isInternalOptOut() {
|
|
2386
|
+
try {
|
|
2387
|
+
return localStore()?.getItem(STORAGE_KEY) === "1";
|
|
2388
|
+
} catch {
|
|
2389
|
+
return false;
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
|
|
2331
2393
|
// src/web-vitals.ts
|
|
2332
2394
|
var WebVitalsTracker = class {
|
|
2333
2395
|
constructor(cfg, report) {
|
|
@@ -2858,15 +2920,6 @@ var VerifierReporter = class {
|
|
|
2858
2920
|
constructor(ctx) {
|
|
2859
2921
|
this.ctx = ctx;
|
|
2860
2922
|
this.reentrancyDepth = 0;
|
|
2861
|
-
/** The live verifier set — attached by the SDK right after init so the
|
|
2862
|
-
* emit path can schema-lock its OWN outgoing telemetry against the real
|
|
2863
|
-
* payload. Null until attached (boot-time reports still work without it). */
|
|
2864
|
-
this.verifiers = null;
|
|
2865
|
-
}
|
|
2866
|
-
/** Hand the reporter the live verifier set so `reportFail` can run the
|
|
2867
|
-
* `onReportContractFailure` hook on the exact payload it's about to emit. */
|
|
2868
|
-
attachVerifiers(verifiers) {
|
|
2869
|
-
this.verifiers = verifiers;
|
|
2870
2923
|
}
|
|
2871
2924
|
/**
|
|
2872
2925
|
* Report a verifier result. Pass `operation` for hot-path results
|
|
@@ -2895,7 +2948,7 @@ var VerifierReporter = class {
|
|
|
2895
2948
|
if (this.reentrancyDepth > 0) return;
|
|
2896
2949
|
this.reentrancyDepth += 1;
|
|
2897
2950
|
try {
|
|
2898
|
-
|
|
2951
|
+
this.ctx.emitTelemetry({
|
|
2899
2952
|
contract_id: result.contractId,
|
|
2900
2953
|
sdk_version: this.ctx.sdkVersion,
|
|
2901
2954
|
sdk_platform: "web",
|
|
@@ -2903,13 +2956,7 @@ var VerifierReporter = class {
|
|
|
2903
2956
|
run_context: this.ctx.runContext,
|
|
2904
2957
|
run_id: this.ctx.runId,
|
|
2905
2958
|
verification_phase: phase
|
|
2906
|
-
};
|
|
2907
|
-
if (this.verifiers) {
|
|
2908
|
-
runOnReportContractFailure(this.verifiers, this, this.ctx, {
|
|
2909
|
-
outgoingPayload: payload
|
|
2910
|
-
});
|
|
2911
|
-
}
|
|
2912
|
-
this.ctx.emitTelemetry(payload);
|
|
2959
|
+
});
|
|
2913
2960
|
} finally {
|
|
2914
2961
|
this.reentrancyDepth -= 1;
|
|
2915
2962
|
}
|
|
@@ -3199,31 +3246,9 @@ var VERIFIER_FLUSH_INTERVAL_PARITY = {
|
|
|
3199
3246
|
"eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",
|
|
3200
3247
|
nowMs() - t0
|
|
3201
3248
|
);
|
|
3202
|
-
},
|
|
3203
|
-
// Hot-path hook — on every real track() we re-affirm the LIVE configured
|
|
3204
|
-
// flush interval (carried on the observation), so the parity guarantee is
|
|
3205
|
-
// verified against the running SDK in the customer flow, not just a
|
|
3206
|
-
// canonical constant at boot. It can't change per-event, but observing it
|
|
3207
|
-
// per-event is what makes the contract genuinely runtime-verified.
|
|
3208
|
-
hooks: {
|
|
3209
|
-
onTrack(obs) {
|
|
3210
|
-
const t0 = nowMs();
|
|
3211
|
-
const CANONICAL_DEFAULT_MS = 2e3;
|
|
3212
|
-
const ms = obs.flushIntervalMs;
|
|
3213
|
-
if (typeof ms !== "number" || ms < 100 || ms > 6e4) {
|
|
3214
|
-
return fail(
|
|
3215
|
-
"flush-interval-parity",
|
|
3216
|
-
`live eventFlushIntervalMs=${ms} outside reasonable bounds [100, 60000]`,
|
|
3217
|
-
nowMs() - t0
|
|
3218
|
-
);
|
|
3219
|
-
}
|
|
3220
|
-
return pass(
|
|
3221
|
-
"flush-interval-parity",
|
|
3222
|
-
ms === CANONICAL_DEFAULT_MS ? "live eventFlushIntervalMs = 2000ms (canonical parity value)" : `live eventFlushIntervalMs = ${ms}ms (permitted override; canonical default 2000ms)`,
|
|
3223
|
-
nowMs() - t0
|
|
3224
|
-
);
|
|
3225
|
-
}
|
|
3226
3249
|
}
|
|
3250
|
+
// No hot-path hook — the flush interval is set once at start() and
|
|
3251
|
+
// never changes per-operation.
|
|
3227
3252
|
};
|
|
3228
3253
|
function buildFlushIntervalVerifier(configuredIntervalMs) {
|
|
3229
3254
|
return {
|
|
@@ -3350,26 +3375,6 @@ var CONTRACT_FAILED_FORBIDDEN_FIELDS = [
|
|
|
3350
3375
|
"referrer",
|
|
3351
3376
|
"deviceId"
|
|
3352
3377
|
];
|
|
3353
|
-
function contractFailedSchemaViolation(keys) {
|
|
3354
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
3355
|
-
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3356
|
-
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3357
|
-
]);
|
|
3358
|
-
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3359
|
-
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3360
|
-
if (!keys.includes(required)) return `missing required field: ${required}`;
|
|
3361
|
-
}
|
|
3362
|
-
for (const k of keys) {
|
|
3363
|
-
if (forbidden.has(k)) return `forbidden field on wire: ${k}`;
|
|
3364
|
-
}
|
|
3365
|
-
for (const k of keys) {
|
|
3366
|
-
if (!allowed.has(k)) {
|
|
3367
|
-
return `unrecognised field on wire: ${k} (not in required \u222A optional)`;
|
|
3368
|
-
}
|
|
3369
|
-
}
|
|
3370
|
-
return null;
|
|
3371
|
-
}
|
|
3372
|
-
var CONTRACT_FAILED_OK_EVIDENCE = `fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`;
|
|
3373
3378
|
var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
3374
3379
|
contractId: "contract-failed-payload-schema-lock",
|
|
3375
3380
|
bootTest() {
|
|
@@ -3384,35 +3389,43 @@ var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
|
3384
3389
|
verification_phase: "boot"
|
|
3385
3390
|
};
|
|
3386
3391
|
const keys = Object.keys(syntheticPayload);
|
|
3387
|
-
const
|
|
3388
|
-
|
|
3389
|
-
|
|
3392
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
3393
|
+
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3394
|
+
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3395
|
+
]);
|
|
3396
|
+
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3397
|
+
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3398
|
+
if (!keys.includes(required)) {
|
|
3399
|
+
return fail(
|
|
3400
|
+
"contract-failed-payload-schema-lock",
|
|
3401
|
+
`missing required field: ${required}`,
|
|
3402
|
+
nowMs() - t0
|
|
3403
|
+
);
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
for (const k of keys) {
|
|
3407
|
+
if (forbidden.has(k)) {
|
|
3408
|
+
return fail(
|
|
3409
|
+
"contract-failed-payload-schema-lock",
|
|
3410
|
+
`forbidden field on wire: ${k}`,
|
|
3411
|
+
nowMs() - t0
|
|
3412
|
+
);
|
|
3413
|
+
}
|
|
3414
|
+
}
|
|
3415
|
+
for (const k of keys) {
|
|
3416
|
+
if (!allowed.has(k)) {
|
|
3417
|
+
return fail(
|
|
3418
|
+
"contract-failed-payload-schema-lock",
|
|
3419
|
+
`unrecognised field on wire: ${k} (not in required \u222A optional)`,
|
|
3420
|
+
nowMs() - t0
|
|
3421
|
+
);
|
|
3422
|
+
}
|
|
3390
3423
|
}
|
|
3391
3424
|
return pass(
|
|
3392
3425
|
"contract-failed-payload-schema-lock",
|
|
3393
|
-
`${keys.length} ${
|
|
3426
|
+
`${keys.length} fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`,
|
|
3394
3427
|
nowMs() - t0
|
|
3395
3428
|
);
|
|
3396
|
-
},
|
|
3397
|
-
// Hot-path hook — fires on the REAL reportFail emit (VerifierReporter,
|
|
3398
|
-
// inside the re-entrancy guard) against the exact payload about to go on
|
|
3399
|
-
// the wire. This is the assertion the guard at reportFail was built in
|
|
3400
|
-
// anticipation of: every reliability-channel write is schema-locked in the
|
|
3401
|
-
// field, against real data, not just the synthetic boot mirror.
|
|
3402
|
-
hooks: {
|
|
3403
|
-
onReportContractFailure(obs) {
|
|
3404
|
-
const t0 = nowMs();
|
|
3405
|
-
const keys = Object.keys(obs.outgoingPayload);
|
|
3406
|
-
const violation = contractFailedSchemaViolation(keys);
|
|
3407
|
-
if (violation) {
|
|
3408
|
-
return fail("contract-failed-payload-schema-lock", violation, nowMs() - t0);
|
|
3409
|
-
}
|
|
3410
|
-
return pass(
|
|
3411
|
-
"contract-failed-payload-schema-lock",
|
|
3412
|
-
`${keys.length} ${CONTRACT_FAILED_OK_EVIDENCE}`,
|
|
3413
|
-
nowMs() - t0
|
|
3414
|
-
);
|
|
3415
|
-
}
|
|
3416
3429
|
}
|
|
3417
3430
|
};
|
|
3418
3431
|
var BACKEND_WIRE_CODES = Object.freeze([
|
|
@@ -3463,39 +3476,6 @@ var VERIFIER_SDK_ERROR_CODES_CATALOGUE = {
|
|
|
3463
3476
|
nowMs() - t0
|
|
3464
3477
|
);
|
|
3465
3478
|
}
|
|
3466
|
-
},
|
|
3467
|
-
// Hot-path hook — when the SDK parses a real wire error, assert the code
|
|
3468
|
-
// the customer actually hit carries usable remediation in the shipped
|
|
3469
|
-
// catalogue. Scoped to BACKEND_WIRE_CODES (the contract's set); other
|
|
3470
|
-
// codes are out of scope and pass. This turns the catalogue from a
|
|
3471
|
-
// boot-only completeness claim into a per-error field assertion: a backend
|
|
3472
|
-
// code that ships without remediation is caught the first time a customer
|
|
3473
|
-
// hits it, not only if the off-by-default boot self-test ran.
|
|
3474
|
-
hooks: {
|
|
3475
|
-
onErrorParse(obs) {
|
|
3476
|
-
const t0 = nowMs();
|
|
3477
|
-
const code = obs.errorCode;
|
|
3478
|
-
if (!code || !BACKEND_WIRE_CODES.includes(code)) {
|
|
3479
|
-
return pass(
|
|
3480
|
-
"sdk-error-codes-catalogue",
|
|
3481
|
-
`wire code "${code || "(none)"}" is out of the backend-catalogue scope`,
|
|
3482
|
-
nowMs() - t0
|
|
3483
|
-
);
|
|
3484
|
-
}
|
|
3485
|
-
const entry = getErrorCode(code);
|
|
3486
|
-
if (!entry || !entry.description || entry.description.trim().length === 0 || !entry.resolution || entry.resolution.trim().length === 0) {
|
|
3487
|
-
return fail(
|
|
3488
|
-
"sdk-error-codes-catalogue",
|
|
3489
|
-
`backend wire code "${code}" hit in the field has no description+resolution in the shipped catalogue`,
|
|
3490
|
-
nowMs() - t0
|
|
3491
|
-
);
|
|
3492
|
-
}
|
|
3493
|
-
return pass(
|
|
3494
|
-
"sdk-error-codes-catalogue",
|
|
3495
|
-
`backend wire code "${code}" carries description + resolution`,
|
|
3496
|
-
nowMs() - t0
|
|
3497
|
-
);
|
|
3498
|
-
}
|
|
3499
3479
|
}
|
|
3500
3480
|
};
|
|
3501
3481
|
var STATIC_VERIFIERS = Object.freeze([
|
|
@@ -3619,24 +3599,6 @@ function runOnErrorParse(verifiers, reporter, ctx, obs) {
|
|
|
3619
3599
|
reporter.report(result, "hot_path", "errorParse");
|
|
3620
3600
|
}
|
|
3621
3601
|
}
|
|
3622
|
-
function runOnReportContractFailure(verifiers, reporter, ctx, obs) {
|
|
3623
|
-
if (ctx.disableContractAssertions) return;
|
|
3624
|
-
for (const verifier of verifiers) {
|
|
3625
|
-
const hook = verifier.hooks?.onReportContractFailure;
|
|
3626
|
-
if (!hook) continue;
|
|
3627
|
-
let result;
|
|
3628
|
-
try {
|
|
3629
|
-
result = hook(obs);
|
|
3630
|
-
} catch (err) {
|
|
3631
|
-
result = fail(
|
|
3632
|
-
verifier.contractId,
|
|
3633
|
-
`hook threw: ${err.message?.slice(0, 80) ?? "unknown"}`,
|
|
3634
|
-
0
|
|
3635
|
-
);
|
|
3636
|
-
}
|
|
3637
|
-
reporter.report(result, "hot_path", "reportContractFailure");
|
|
3638
|
-
}
|
|
3639
|
-
}
|
|
3640
3602
|
function defaultDebugModeFlag() {
|
|
3641
3603
|
try {
|
|
3642
3604
|
if (typeof process !== "undefined" && process.env) {
|
|
@@ -3788,18 +3750,18 @@ function isInAppFrame(filename) {
|
|
|
3788
3750
|
if (/\/crossdeck\.umd\.min\.js$/.test(filename)) return false;
|
|
3789
3751
|
return true;
|
|
3790
3752
|
}
|
|
3791
|
-
function fingerprintError(message, frames,
|
|
3753
|
+
function fingerprintError(message, frames, location2) {
|
|
3792
3754
|
const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
|
|
3793
3755
|
const parts = [
|
|
3794
3756
|
(message || "").slice(0, 200),
|
|
3795
3757
|
...inAppFrames.map((f) => `${f.function}@${f.filename}:${f.lineno}`)
|
|
3796
3758
|
];
|
|
3797
|
-
if (inAppFrames.length === 0 &&
|
|
3759
|
+
if (inAppFrames.length === 0 && location2) {
|
|
3798
3760
|
const loc = [
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3761
|
+
location2.errorType ?? "",
|
|
3762
|
+
location2.filename ?? "",
|
|
3763
|
+
location2.lineno ?? "",
|
|
3764
|
+
location2.colno ?? ""
|
|
3803
3765
|
].join(":");
|
|
3804
3766
|
if (loc !== ":::") parts.push(loc);
|
|
3805
3767
|
}
|
|
@@ -4469,9 +4431,6 @@ var CrossdeckClient = class {
|
|
|
4469
4431
|
this.verifiers = null;
|
|
4470
4432
|
this.verifierReporter = null;
|
|
4471
4433
|
this.verifierCtx = null;
|
|
4472
|
-
// The live configured event-flush interval, surfaced to the track-path
|
|
4473
|
-
// verifier so flush-interval-parity validates the real cadence per event.
|
|
4474
|
-
this.flushIntervalMs = 2e3;
|
|
4475
4434
|
}
|
|
4476
4435
|
/**
|
|
4477
4436
|
* Boot the SDK. Idempotent — calling init twice with the same options
|
|
@@ -4648,6 +4607,7 @@ var CrossdeckClient = class {
|
|
|
4648
4607
|
persistIdentity ? effectiveStorage : new MemoryStorage(),
|
|
4649
4608
|
opts.storagePrefix
|
|
4650
4609
|
);
|
|
4610
|
+
processInternalOptOutUrl();
|
|
4651
4611
|
const consent = new ConsentManager({ respectDnt: options.respectDnt === true });
|
|
4652
4612
|
if (consent.isDntDenied) {
|
|
4653
4613
|
debug.emit(
|
|
@@ -4751,8 +4711,6 @@ var CrossdeckClient = class {
|
|
|
4751
4711
|
this.verifierReporter = new VerifierReporter(this.verifierCtx);
|
|
4752
4712
|
const flushVerifier = buildFlushIntervalVerifier(opts.eventFlushIntervalMs);
|
|
4753
4713
|
this.verifiers = Object.freeze([...STATIC_VERIFIERS, flushVerifier]);
|
|
4754
|
-
this.flushIntervalMs = opts.eventFlushIntervalMs;
|
|
4755
|
-
this.verifierReporter.attachVerifiers(this.verifiers);
|
|
4756
4714
|
if (localDevMode) {
|
|
4757
4715
|
const verifyAtBootLocal = options.verifyContractsAtBoot ?? debugDefault;
|
|
4758
4716
|
if (verifyAtBootLocal && this.verifierReporter) {
|
|
@@ -5303,8 +5261,27 @@ var CrossdeckClient = class {
|
|
|
5303
5261
|
);
|
|
5304
5262
|
}
|
|
5305
5263
|
}
|
|
5264
|
+
const seq = s.autoTracker?.nextSeq() ?? 0;
|
|
5265
|
+
const occurrenceTimestamp = Date.now();
|
|
5306
5266
|
s.autoTracker?.markActivity();
|
|
5307
|
-
const
|
|
5267
|
+
const wireContext = {};
|
|
5268
|
+
const di = s.deviceInfo;
|
|
5269
|
+
if (di.os) wireContext.os = di.os;
|
|
5270
|
+
if (di.osVersion) wireContext.osVersion = di.osVersion;
|
|
5271
|
+
const appVer = s.options.appVersion;
|
|
5272
|
+
if (appVer) wireContext.appVersion = appVer;
|
|
5273
|
+
wireContext.sdkName = SDK_NAME;
|
|
5274
|
+
wireContext.sdkVersion = s.options.sdkVersion;
|
|
5275
|
+
if (di.locale) wireContext.locale = di.locale;
|
|
5276
|
+
if (di.timezone) wireContext.timezone = di.timezone;
|
|
5277
|
+
if (di.browser) wireContext.browser = di.browser;
|
|
5278
|
+
if (di.browserVersion) wireContext.browserVersion = di.browserVersion;
|
|
5279
|
+
const enriched = {};
|
|
5280
|
+
if (di.screenWidth !== void 0) enriched.screenWidth = di.screenWidth;
|
|
5281
|
+
if (di.screenHeight !== void 0) enriched.screenHeight = di.screenHeight;
|
|
5282
|
+
if (di.viewportWidth !== void 0) enriched.viewportWidth = di.viewportWidth;
|
|
5283
|
+
if (di.viewportHeight !== void 0) enriched.viewportHeight = di.viewportHeight;
|
|
5284
|
+
if (di.devicePixelRatio !== void 0) enriched.devicePixelRatio = di.devicePixelRatio;
|
|
5308
5285
|
const sessionId = s.autoTracker?.currentSessionId;
|
|
5309
5286
|
if (sessionId) enriched.sessionId = sessionId;
|
|
5310
5287
|
const pageviewId = s.autoTracker?.currentPageviewId;
|
|
@@ -5327,17 +5304,24 @@ var CrossdeckClient = class {
|
|
|
5327
5304
|
}
|
|
5328
5305
|
}
|
|
5329
5306
|
const supers = s.superProps.getSuperProperties();
|
|
5330
|
-
Object.
|
|
5307
|
+
for (const k of Object.keys(supers)) {
|
|
5308
|
+
if (!(k in enriched)) enriched[k] = supers[k];
|
|
5309
|
+
}
|
|
5331
5310
|
const groupIds = s.superProps.getGroupIds();
|
|
5332
5311
|
if (Object.keys(groupIds).length > 0) {
|
|
5333
5312
|
enriched.$groups = groupIds;
|
|
5334
5313
|
}
|
|
5335
5314
|
Object.assign(enriched, validation.properties);
|
|
5315
|
+
if (isInternalOptOut()) {
|
|
5316
|
+
enriched[INTERNAL_OPT_OUT_PROPERTY] = true;
|
|
5317
|
+
}
|
|
5336
5318
|
const finalProperties = s.scrubPii ? scrubPiiFromProperties(enriched) : enriched;
|
|
5337
5319
|
const event = {
|
|
5338
5320
|
eventId: this.mintEventId(),
|
|
5339
5321
|
name,
|
|
5340
|
-
timestamp:
|
|
5322
|
+
timestamp: occurrenceTimestamp,
|
|
5323
|
+
seq,
|
|
5324
|
+
context: wireContext,
|
|
5341
5325
|
properties: finalProperties
|
|
5342
5326
|
};
|
|
5343
5327
|
Object.assign(event, this.identityHintForEvent());
|
|
@@ -5347,8 +5331,7 @@ var CrossdeckClient = class {
|
|
|
5347
5331
|
callerProperties: validation.properties,
|
|
5348
5332
|
superProperties: supers,
|
|
5349
5333
|
deviceProperties: s.deviceInfo,
|
|
5350
|
-
mergedProperties: enriched
|
|
5351
|
-
flushIntervalMs: this.flushIntervalMs
|
|
5334
|
+
mergedProperties: enriched
|
|
5352
5335
|
});
|
|
5353
5336
|
}
|
|
5354
5337
|
if (!isError && !isWebVital) {
|