@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/error-codes.json
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -99,7 +99,7 @@ function typeMapForStatus(status) {
|
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// src/_version.ts
|
|
102
|
-
var SDK_VERSION = "1.
|
|
102
|
+
var SDK_VERSION = "1.7.0";
|
|
103
103
|
var SDK_NAME = "@cross-deck/web";
|
|
104
104
|
|
|
105
105
|
// src/http.ts
|
|
@@ -1015,9 +1015,13 @@ var EventQueue = class {
|
|
|
1015
1015
|
const env = this.cfg.envelope();
|
|
1016
1016
|
const result = await this.cfg.http.request("POST", "/events", {
|
|
1017
1017
|
body: {
|
|
1018
|
-
//
|
|
1019
|
-
//
|
|
1020
|
-
//
|
|
1018
|
+
// Event Envelope v1 batch envelope (backend/docs/
|
|
1019
|
+
// event-envelope-spec-v1.md §1). `envelopeVersion` is the
|
|
1020
|
+
// schema/wire version the server parses against ("can I parse
|
|
1021
|
+
// this?") and is DISTINCT from `sdk.version` ("which build is in
|
|
1022
|
+
// the wild?") — two questions, two fields, never conflated. The
|
|
1023
|
+
// backend refuses payloads with a missing/unknown envelopeVersion.
|
|
1024
|
+
envelopeVersion: 1,
|
|
1021
1025
|
appId: env.appId,
|
|
1022
1026
|
environment: env.environment,
|
|
1023
1027
|
sdk: env.sdk,
|
|
@@ -1472,6 +1476,15 @@ var AutoTracker = class {
|
|
|
1472
1476
|
this.cleanups = [];
|
|
1473
1477
|
/** Last time we flushed lastActivityAt to storage (throttle gate). */
|
|
1474
1478
|
this.lastPersistAt = 0;
|
|
1479
|
+
/**
|
|
1480
|
+
* Event Envelope v1 §3 — per-session monotonic sequence counter.
|
|
1481
|
+
* The single owner of the seq counter lives here, alongside all other
|
|
1482
|
+
* session state. Incremented atomically at track() time (via nextSeq()),
|
|
1483
|
+
* reset to 0 whenever a new session boundary is crossed (startNewSession
|
|
1484
|
+
* path + resetSession). Persists across background/foreground within a
|
|
1485
|
+
* session — only a real session boundary (not a tab hide/show) resets it.
|
|
1486
|
+
*/
|
|
1487
|
+
this._sessionSeq = 0;
|
|
1475
1488
|
/**
|
|
1476
1489
|
* Stable per-page-view identifier. Minted at every `page.viewed`
|
|
1477
1490
|
* emission and attached to every subsequent event until the next
|
|
@@ -1556,6 +1569,20 @@ var AutoTracker = class {
|
|
|
1556
1569
|
get currentAcquisition() {
|
|
1557
1570
|
return this.session?.acquisition ?? EMPTY_ACQUISITION;
|
|
1558
1571
|
}
|
|
1572
|
+
/**
|
|
1573
|
+
* Event Envelope v1 §3 — return the next seq value for the current session
|
|
1574
|
+
* and advance the counter. Called SYNCHRONOUSLY at track() time, before any
|
|
1575
|
+
* async dispatch, so the seq assignment order is deterministic (call order,
|
|
1576
|
+
* not scheduler luck). The counter is reset to 0 at every session boundary;
|
|
1577
|
+
* it is NOT reset by tab hide/show (spec §3 clause 1: backgrounding does not
|
|
1578
|
+
* reset seq). When no session is active (Node, before init, after uninstall),
|
|
1579
|
+
* returns 0 and leaves the counter unchanged — fallback, not an error.
|
|
1580
|
+
*/
|
|
1581
|
+
nextSeq() {
|
|
1582
|
+
const seq = this._sessionSeq;
|
|
1583
|
+
this._sessionSeq += 1;
|
|
1584
|
+
return seq;
|
|
1585
|
+
}
|
|
1559
1586
|
// ---------- sessions ----------
|
|
1560
1587
|
installSessionTracking() {
|
|
1561
1588
|
const now = Date.now();
|
|
@@ -1607,6 +1634,7 @@ var AutoTracker = class {
|
|
|
1607
1634
|
}
|
|
1608
1635
|
startNewSession() {
|
|
1609
1636
|
const now = Date.now();
|
|
1637
|
+
this._sessionSeq = 0;
|
|
1610
1638
|
return {
|
|
1611
1639
|
sessionId: mintSessionId(),
|
|
1612
1640
|
startedAt: now,
|
|
@@ -2335,6 +2363,40 @@ function writeJson(storage, key, value) {
|
|
|
2335
2363
|
}
|
|
2336
2364
|
}
|
|
2337
2365
|
|
|
2366
|
+
// src/internal-opt-out.ts
|
|
2367
|
+
var INTERNAL_OPT_OUT_PROPERTY = "$crossdeck_internal";
|
|
2368
|
+
var STORAGE_KEY = "crossdeck.internalOptOut";
|
|
2369
|
+
function localStore() {
|
|
2370
|
+
try {
|
|
2371
|
+
return typeof localStorage !== "undefined" ? localStorage : null;
|
|
2372
|
+
} catch {
|
|
2373
|
+
return null;
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
function processInternalOptOutUrl() {
|
|
2377
|
+
try {
|
|
2378
|
+
const search = typeof location !== "undefined" ? location.search : "";
|
|
2379
|
+
const params = new URLSearchParams(search || "");
|
|
2380
|
+
if (!params.has("crossdeck_internal")) return;
|
|
2381
|
+
const store = localStore();
|
|
2382
|
+
if (!store) return;
|
|
2383
|
+
const v = params.get("crossdeck_internal");
|
|
2384
|
+
if (v === "1" || v === "true") {
|
|
2385
|
+
store.setItem(STORAGE_KEY, "1");
|
|
2386
|
+
} else if (v === "0" || v === "false") {
|
|
2387
|
+
store.removeItem(STORAGE_KEY);
|
|
2388
|
+
}
|
|
2389
|
+
} catch {
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2392
|
+
function isInternalOptOut() {
|
|
2393
|
+
try {
|
|
2394
|
+
return localStore()?.getItem(STORAGE_KEY) === "1";
|
|
2395
|
+
} catch {
|
|
2396
|
+
return false;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2338
2400
|
// src/web-vitals.ts
|
|
2339
2401
|
var WebVitalsTracker = class {
|
|
2340
2402
|
constructor(cfg, report) {
|
|
@@ -2865,15 +2927,6 @@ var VerifierReporter = class {
|
|
|
2865
2927
|
constructor(ctx) {
|
|
2866
2928
|
this.ctx = ctx;
|
|
2867
2929
|
this.reentrancyDepth = 0;
|
|
2868
|
-
/** The live verifier set — attached by the SDK right after init so the
|
|
2869
|
-
* emit path can schema-lock its OWN outgoing telemetry against the real
|
|
2870
|
-
* payload. Null until attached (boot-time reports still work without it). */
|
|
2871
|
-
this.verifiers = null;
|
|
2872
|
-
}
|
|
2873
|
-
/** Hand the reporter the live verifier set so `reportFail` can run the
|
|
2874
|
-
* `onReportContractFailure` hook on the exact payload it's about to emit. */
|
|
2875
|
-
attachVerifiers(verifiers) {
|
|
2876
|
-
this.verifiers = verifiers;
|
|
2877
2930
|
}
|
|
2878
2931
|
/**
|
|
2879
2932
|
* Report a verifier result. Pass `operation` for hot-path results
|
|
@@ -2902,7 +2955,7 @@ var VerifierReporter = class {
|
|
|
2902
2955
|
if (this.reentrancyDepth > 0) return;
|
|
2903
2956
|
this.reentrancyDepth += 1;
|
|
2904
2957
|
try {
|
|
2905
|
-
|
|
2958
|
+
this.ctx.emitTelemetry({
|
|
2906
2959
|
contract_id: result.contractId,
|
|
2907
2960
|
sdk_version: this.ctx.sdkVersion,
|
|
2908
2961
|
sdk_platform: "web",
|
|
@@ -2910,13 +2963,7 @@ var VerifierReporter = class {
|
|
|
2910
2963
|
run_context: this.ctx.runContext,
|
|
2911
2964
|
run_id: this.ctx.runId,
|
|
2912
2965
|
verification_phase: phase
|
|
2913
|
-
};
|
|
2914
|
-
if (this.verifiers) {
|
|
2915
|
-
runOnReportContractFailure(this.verifiers, this, this.ctx, {
|
|
2916
|
-
outgoingPayload: payload
|
|
2917
|
-
});
|
|
2918
|
-
}
|
|
2919
|
-
this.ctx.emitTelemetry(payload);
|
|
2966
|
+
});
|
|
2920
2967
|
} finally {
|
|
2921
2968
|
this.reentrancyDepth -= 1;
|
|
2922
2969
|
}
|
|
@@ -3206,31 +3253,9 @@ var VERIFIER_FLUSH_INTERVAL_PARITY = {
|
|
|
3206
3253
|
"eventFlushIntervalMs default = 2000ms (Web/Node/RN/Swift/Android parity)",
|
|
3207
3254
|
nowMs() - t0
|
|
3208
3255
|
);
|
|
3209
|
-
},
|
|
3210
|
-
// Hot-path hook — on every real track() we re-affirm the LIVE configured
|
|
3211
|
-
// flush interval (carried on the observation), so the parity guarantee is
|
|
3212
|
-
// verified against the running SDK in the customer flow, not just a
|
|
3213
|
-
// canonical constant at boot. It can't change per-event, but observing it
|
|
3214
|
-
// per-event is what makes the contract genuinely runtime-verified.
|
|
3215
|
-
hooks: {
|
|
3216
|
-
onTrack(obs) {
|
|
3217
|
-
const t0 = nowMs();
|
|
3218
|
-
const CANONICAL_DEFAULT_MS = 2e3;
|
|
3219
|
-
const ms = obs.flushIntervalMs;
|
|
3220
|
-
if (typeof ms !== "number" || ms < 100 || ms > 6e4) {
|
|
3221
|
-
return fail(
|
|
3222
|
-
"flush-interval-parity",
|
|
3223
|
-
`live eventFlushIntervalMs=${ms} outside reasonable bounds [100, 60000]`,
|
|
3224
|
-
nowMs() - t0
|
|
3225
|
-
);
|
|
3226
|
-
}
|
|
3227
|
-
return pass(
|
|
3228
|
-
"flush-interval-parity",
|
|
3229
|
-
ms === CANONICAL_DEFAULT_MS ? "live eventFlushIntervalMs = 2000ms (canonical parity value)" : `live eventFlushIntervalMs = ${ms}ms (permitted override; canonical default 2000ms)`,
|
|
3230
|
-
nowMs() - t0
|
|
3231
|
-
);
|
|
3232
|
-
}
|
|
3233
3256
|
}
|
|
3257
|
+
// No hot-path hook — the flush interval is set once at start() and
|
|
3258
|
+
// never changes per-operation.
|
|
3234
3259
|
};
|
|
3235
3260
|
function buildFlushIntervalVerifier(configuredIntervalMs) {
|
|
3236
3261
|
return {
|
|
@@ -3357,26 +3382,6 @@ var CONTRACT_FAILED_FORBIDDEN_FIELDS = [
|
|
|
3357
3382
|
"referrer",
|
|
3358
3383
|
"deviceId"
|
|
3359
3384
|
];
|
|
3360
|
-
function contractFailedSchemaViolation(keys) {
|
|
3361
|
-
const allowed = /* @__PURE__ */ new Set([
|
|
3362
|
-
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3363
|
-
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3364
|
-
]);
|
|
3365
|
-
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3366
|
-
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3367
|
-
if (!keys.includes(required)) return `missing required field: ${required}`;
|
|
3368
|
-
}
|
|
3369
|
-
for (const k of keys) {
|
|
3370
|
-
if (forbidden.has(k)) return `forbidden field on wire: ${k}`;
|
|
3371
|
-
}
|
|
3372
|
-
for (const k of keys) {
|
|
3373
|
-
if (!allowed.has(k)) {
|
|
3374
|
-
return `unrecognised field on wire: ${k} (not in required \u222A optional)`;
|
|
3375
|
-
}
|
|
3376
|
-
}
|
|
3377
|
-
return null;
|
|
3378
|
-
}
|
|
3379
|
-
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`;
|
|
3380
3385
|
var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
3381
3386
|
contractId: "contract-failed-payload-schema-lock",
|
|
3382
3387
|
bootTest() {
|
|
@@ -3391,35 +3396,43 @@ var VERIFIER_CONTRACT_FAILED_PAYLOAD_SCHEMA_LOCK = {
|
|
|
3391
3396
|
verification_phase: "boot"
|
|
3392
3397
|
};
|
|
3393
3398
|
const keys = Object.keys(syntheticPayload);
|
|
3394
|
-
const
|
|
3395
|
-
|
|
3396
|
-
|
|
3399
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
3400
|
+
...CONTRACT_FAILED_REQUIRED_FIELDS,
|
|
3401
|
+
...CONTRACT_FAILED_OPTIONAL_FIELDS
|
|
3402
|
+
]);
|
|
3403
|
+
const forbidden = new Set(CONTRACT_FAILED_FORBIDDEN_FIELDS);
|
|
3404
|
+
for (const required of CONTRACT_FAILED_REQUIRED_FIELDS) {
|
|
3405
|
+
if (!keys.includes(required)) {
|
|
3406
|
+
return fail(
|
|
3407
|
+
"contract-failed-payload-schema-lock",
|
|
3408
|
+
`missing required field: ${required}`,
|
|
3409
|
+
nowMs() - t0
|
|
3410
|
+
);
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
for (const k of keys) {
|
|
3414
|
+
if (forbidden.has(k)) {
|
|
3415
|
+
return fail(
|
|
3416
|
+
"contract-failed-payload-schema-lock",
|
|
3417
|
+
`forbidden field on wire: ${k}`,
|
|
3418
|
+
nowMs() - t0
|
|
3419
|
+
);
|
|
3420
|
+
}
|
|
3421
|
+
}
|
|
3422
|
+
for (const k of keys) {
|
|
3423
|
+
if (!allowed.has(k)) {
|
|
3424
|
+
return fail(
|
|
3425
|
+
"contract-failed-payload-schema-lock",
|
|
3426
|
+
`unrecognised field on wire: ${k} (not in required \u222A optional)`,
|
|
3427
|
+
nowMs() - t0
|
|
3428
|
+
);
|
|
3429
|
+
}
|
|
3397
3430
|
}
|
|
3398
3431
|
return pass(
|
|
3399
3432
|
"contract-failed-payload-schema-lock",
|
|
3400
|
-
`${keys.length} ${
|
|
3433
|
+
`${keys.length} fields \u2286 required(${CONTRACT_FAILED_REQUIRED_FIELDS.length}) \u222A optional(${CONTRACT_FAILED_OPTIONAL_FIELDS.length}); ${CONTRACT_FAILED_FORBIDDEN_FIELDS.length} forbidden absent`,
|
|
3401
3434
|
nowMs() - t0
|
|
3402
3435
|
);
|
|
3403
|
-
},
|
|
3404
|
-
// Hot-path hook — fires on the REAL reportFail emit (VerifierReporter,
|
|
3405
|
-
// inside the re-entrancy guard) against the exact payload about to go on
|
|
3406
|
-
// the wire. This is the assertion the guard at reportFail was built in
|
|
3407
|
-
// anticipation of: every reliability-channel write is schema-locked in the
|
|
3408
|
-
// field, against real data, not just the synthetic boot mirror.
|
|
3409
|
-
hooks: {
|
|
3410
|
-
onReportContractFailure(obs) {
|
|
3411
|
-
const t0 = nowMs();
|
|
3412
|
-
const keys = Object.keys(obs.outgoingPayload);
|
|
3413
|
-
const violation = contractFailedSchemaViolation(keys);
|
|
3414
|
-
if (violation) {
|
|
3415
|
-
return fail("contract-failed-payload-schema-lock", violation, nowMs() - t0);
|
|
3416
|
-
}
|
|
3417
|
-
return pass(
|
|
3418
|
-
"contract-failed-payload-schema-lock",
|
|
3419
|
-
`${keys.length} ${CONTRACT_FAILED_OK_EVIDENCE}`,
|
|
3420
|
-
nowMs() - t0
|
|
3421
|
-
);
|
|
3422
|
-
}
|
|
3423
3436
|
}
|
|
3424
3437
|
};
|
|
3425
3438
|
var BACKEND_WIRE_CODES = Object.freeze([
|
|
@@ -3470,39 +3483,6 @@ var VERIFIER_SDK_ERROR_CODES_CATALOGUE = {
|
|
|
3470
3483
|
nowMs() - t0
|
|
3471
3484
|
);
|
|
3472
3485
|
}
|
|
3473
|
-
},
|
|
3474
|
-
// Hot-path hook — when the SDK parses a real wire error, assert the code
|
|
3475
|
-
// the customer actually hit carries usable remediation in the shipped
|
|
3476
|
-
// catalogue. Scoped to BACKEND_WIRE_CODES (the contract's set); other
|
|
3477
|
-
// codes are out of scope and pass. This turns the catalogue from a
|
|
3478
|
-
// boot-only completeness claim into a per-error field assertion: a backend
|
|
3479
|
-
// code that ships without remediation is caught the first time a customer
|
|
3480
|
-
// hits it, not only if the off-by-default boot self-test ran.
|
|
3481
|
-
hooks: {
|
|
3482
|
-
onErrorParse(obs) {
|
|
3483
|
-
const t0 = nowMs();
|
|
3484
|
-
const code = obs.errorCode;
|
|
3485
|
-
if (!code || !BACKEND_WIRE_CODES.includes(code)) {
|
|
3486
|
-
return pass(
|
|
3487
|
-
"sdk-error-codes-catalogue",
|
|
3488
|
-
`wire code "${code || "(none)"}" is out of the backend-catalogue scope`,
|
|
3489
|
-
nowMs() - t0
|
|
3490
|
-
);
|
|
3491
|
-
}
|
|
3492
|
-
const entry = getErrorCode(code);
|
|
3493
|
-
if (!entry || !entry.description || entry.description.trim().length === 0 || !entry.resolution || entry.resolution.trim().length === 0) {
|
|
3494
|
-
return fail(
|
|
3495
|
-
"sdk-error-codes-catalogue",
|
|
3496
|
-
`backend wire code "${code}" hit in the field has no description+resolution in the shipped catalogue`,
|
|
3497
|
-
nowMs() - t0
|
|
3498
|
-
);
|
|
3499
|
-
}
|
|
3500
|
-
return pass(
|
|
3501
|
-
"sdk-error-codes-catalogue",
|
|
3502
|
-
`backend wire code "${code}" carries description + resolution`,
|
|
3503
|
-
nowMs() - t0
|
|
3504
|
-
);
|
|
3505
|
-
}
|
|
3506
3486
|
}
|
|
3507
3487
|
};
|
|
3508
3488
|
var STATIC_VERIFIERS = Object.freeze([
|
|
@@ -3626,24 +3606,6 @@ function runOnErrorParse(verifiers, reporter, ctx, obs) {
|
|
|
3626
3606
|
reporter.report(result, "hot_path", "errorParse");
|
|
3627
3607
|
}
|
|
3628
3608
|
}
|
|
3629
|
-
function runOnReportContractFailure(verifiers, reporter, ctx, obs) {
|
|
3630
|
-
if (ctx.disableContractAssertions) return;
|
|
3631
|
-
for (const verifier of verifiers) {
|
|
3632
|
-
const hook = verifier.hooks?.onReportContractFailure;
|
|
3633
|
-
if (!hook) continue;
|
|
3634
|
-
let result;
|
|
3635
|
-
try {
|
|
3636
|
-
result = hook(obs);
|
|
3637
|
-
} catch (err) {
|
|
3638
|
-
result = fail(
|
|
3639
|
-
verifier.contractId,
|
|
3640
|
-
`hook threw: ${err.message?.slice(0, 80) ?? "unknown"}`,
|
|
3641
|
-
0
|
|
3642
|
-
);
|
|
3643
|
-
}
|
|
3644
|
-
reporter.report(result, "hot_path", "reportContractFailure");
|
|
3645
|
-
}
|
|
3646
|
-
}
|
|
3647
3609
|
function defaultDebugModeFlag() {
|
|
3648
3610
|
try {
|
|
3649
3611
|
if (typeof process !== "undefined" && process.env) {
|
|
@@ -3795,18 +3757,18 @@ function isInAppFrame(filename) {
|
|
|
3795
3757
|
if (/\/crossdeck\.umd\.min\.js$/.test(filename)) return false;
|
|
3796
3758
|
return true;
|
|
3797
3759
|
}
|
|
3798
|
-
function fingerprintError(message, frames,
|
|
3760
|
+
function fingerprintError(message, frames, location2) {
|
|
3799
3761
|
const inAppFrames = frames.filter((f) => f.in_app).slice(0, 3);
|
|
3800
3762
|
const parts = [
|
|
3801
3763
|
(message || "").slice(0, 200),
|
|
3802
3764
|
...inAppFrames.map((f) => `${f.function}@${f.filename}:${f.lineno}`)
|
|
3803
3765
|
];
|
|
3804
|
-
if (inAppFrames.length === 0 &&
|
|
3766
|
+
if (inAppFrames.length === 0 && location2) {
|
|
3805
3767
|
const loc = [
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
|
|
3768
|
+
location2.errorType ?? "",
|
|
3769
|
+
location2.filename ?? "",
|
|
3770
|
+
location2.lineno ?? "",
|
|
3771
|
+
location2.colno ?? ""
|
|
3810
3772
|
].join(":");
|
|
3811
3773
|
if (loc !== ":::") parts.push(loc);
|
|
3812
3774
|
}
|
|
@@ -4476,9 +4438,6 @@ var CrossdeckClient = class {
|
|
|
4476
4438
|
this.verifiers = null;
|
|
4477
4439
|
this.verifierReporter = null;
|
|
4478
4440
|
this.verifierCtx = null;
|
|
4479
|
-
// The live configured event-flush interval, surfaced to the track-path
|
|
4480
|
-
// verifier so flush-interval-parity validates the real cadence per event.
|
|
4481
|
-
this.flushIntervalMs = 2e3;
|
|
4482
4441
|
}
|
|
4483
4442
|
/**
|
|
4484
4443
|
* Boot the SDK. Idempotent — calling init twice with the same options
|
|
@@ -4655,6 +4614,7 @@ var CrossdeckClient = class {
|
|
|
4655
4614
|
persistIdentity ? effectiveStorage : new MemoryStorage(),
|
|
4656
4615
|
opts.storagePrefix
|
|
4657
4616
|
);
|
|
4617
|
+
processInternalOptOutUrl();
|
|
4658
4618
|
const consent = new ConsentManager({ respectDnt: options.respectDnt === true });
|
|
4659
4619
|
if (consent.isDntDenied) {
|
|
4660
4620
|
debug.emit(
|
|
@@ -4758,8 +4718,6 @@ var CrossdeckClient = class {
|
|
|
4758
4718
|
this.verifierReporter = new VerifierReporter(this.verifierCtx);
|
|
4759
4719
|
const flushVerifier = buildFlushIntervalVerifier(opts.eventFlushIntervalMs);
|
|
4760
4720
|
this.verifiers = Object.freeze([...STATIC_VERIFIERS, flushVerifier]);
|
|
4761
|
-
this.flushIntervalMs = opts.eventFlushIntervalMs;
|
|
4762
|
-
this.verifierReporter.attachVerifiers(this.verifiers);
|
|
4763
4721
|
if (localDevMode) {
|
|
4764
4722
|
const verifyAtBootLocal = options.verifyContractsAtBoot ?? debugDefault;
|
|
4765
4723
|
if (verifyAtBootLocal && this.verifierReporter) {
|
|
@@ -5310,8 +5268,27 @@ var CrossdeckClient = class {
|
|
|
5310
5268
|
);
|
|
5311
5269
|
}
|
|
5312
5270
|
}
|
|
5271
|
+
const seq = s.autoTracker?.nextSeq() ?? 0;
|
|
5272
|
+
const occurrenceTimestamp = Date.now();
|
|
5313
5273
|
s.autoTracker?.markActivity();
|
|
5314
|
-
const
|
|
5274
|
+
const wireContext = {};
|
|
5275
|
+
const di = s.deviceInfo;
|
|
5276
|
+
if (di.os) wireContext.os = di.os;
|
|
5277
|
+
if (di.osVersion) wireContext.osVersion = di.osVersion;
|
|
5278
|
+
const appVer = s.options.appVersion;
|
|
5279
|
+
if (appVer) wireContext.appVersion = appVer;
|
|
5280
|
+
wireContext.sdkName = SDK_NAME;
|
|
5281
|
+
wireContext.sdkVersion = s.options.sdkVersion;
|
|
5282
|
+
if (di.locale) wireContext.locale = di.locale;
|
|
5283
|
+
if (di.timezone) wireContext.timezone = di.timezone;
|
|
5284
|
+
if (di.browser) wireContext.browser = di.browser;
|
|
5285
|
+
if (di.browserVersion) wireContext.browserVersion = di.browserVersion;
|
|
5286
|
+
const enriched = {};
|
|
5287
|
+
if (di.screenWidth !== void 0) enriched.screenWidth = di.screenWidth;
|
|
5288
|
+
if (di.screenHeight !== void 0) enriched.screenHeight = di.screenHeight;
|
|
5289
|
+
if (di.viewportWidth !== void 0) enriched.viewportWidth = di.viewportWidth;
|
|
5290
|
+
if (di.viewportHeight !== void 0) enriched.viewportHeight = di.viewportHeight;
|
|
5291
|
+
if (di.devicePixelRatio !== void 0) enriched.devicePixelRatio = di.devicePixelRatio;
|
|
5315
5292
|
const sessionId = s.autoTracker?.currentSessionId;
|
|
5316
5293
|
if (sessionId) enriched.sessionId = sessionId;
|
|
5317
5294
|
const pageviewId = s.autoTracker?.currentPageviewId;
|
|
@@ -5334,17 +5311,24 @@ var CrossdeckClient = class {
|
|
|
5334
5311
|
}
|
|
5335
5312
|
}
|
|
5336
5313
|
const supers = s.superProps.getSuperProperties();
|
|
5337
|
-
Object.
|
|
5314
|
+
for (const k of Object.keys(supers)) {
|
|
5315
|
+
if (!(k in enriched)) enriched[k] = supers[k];
|
|
5316
|
+
}
|
|
5338
5317
|
const groupIds = s.superProps.getGroupIds();
|
|
5339
5318
|
if (Object.keys(groupIds).length > 0) {
|
|
5340
5319
|
enriched.$groups = groupIds;
|
|
5341
5320
|
}
|
|
5342
5321
|
Object.assign(enriched, validation.properties);
|
|
5322
|
+
if (isInternalOptOut()) {
|
|
5323
|
+
enriched[INTERNAL_OPT_OUT_PROPERTY] = true;
|
|
5324
|
+
}
|
|
5343
5325
|
const finalProperties = s.scrubPii ? scrubPiiFromProperties(enriched) : enriched;
|
|
5344
5326
|
const event = {
|
|
5345
5327
|
eventId: this.mintEventId(),
|
|
5346
5328
|
name,
|
|
5347
|
-
timestamp:
|
|
5329
|
+
timestamp: occurrenceTimestamp,
|
|
5330
|
+
seq,
|
|
5331
|
+
context: wireContext,
|
|
5348
5332
|
properties: finalProperties
|
|
5349
5333
|
};
|
|
5350
5334
|
Object.assign(event, this.identityHintForEvent());
|
|
@@ -5354,8 +5338,7 @@ var CrossdeckClient = class {
|
|
|
5354
5338
|
callerProperties: validation.properties,
|
|
5355
5339
|
superProperties: supers,
|
|
5356
5340
|
deviceProperties: s.deviceInfo,
|
|
5357
|
-
mergedProperties: enriched
|
|
5358
|
-
flushIntervalMs: this.flushIntervalMs
|
|
5341
|
+
mergedProperties: enriched
|
|
5359
5342
|
});
|
|
5360
5343
|
}
|
|
5361
5344
|
if (!isError && !isWebVital) {
|
|
@@ -5700,8 +5683,8 @@ function installUnloadFlush(onUnload) {
|
|
|
5700
5683
|
}
|
|
5701
5684
|
|
|
5702
5685
|
// src/_contracts-bundled.ts
|
|
5703
|
-
var BUNDLED_IN = "@cross-deck/web@1.
|
|
5704
|
-
var SDK_VERSION2 = "1.
|
|
5686
|
+
var BUNDLED_IN = "@cross-deck/web@1.7.0";
|
|
5687
|
+
var SDK_VERSION2 = "1.7.0";
|
|
5705
5688
|
var BUNDLED_CONTRACTS = Object.freeze([
|
|
5706
5689
|
{
|
|
5707
5690
|
"id": "contract-failed-payload-schema-lock",
|
|
@@ -5823,7 +5806,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5823
5806
|
"legal/security/index.html#diagnostic",
|
|
5824
5807
|
"legal/sdk-data/index.html#b-diagnostic"
|
|
5825
5808
|
],
|
|
5826
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5809
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5827
5810
|
"runtimeVerified": true
|
|
5828
5811
|
},
|
|
5829
5812
|
{
|
|
@@ -5863,7 +5846,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5863
5846
|
],
|
|
5864
5847
|
"registeredAt": "2026-05-26",
|
|
5865
5848
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 8 (codifies existing contract)",
|
|
5866
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5849
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5867
5850
|
"runtimeVerified": true
|
|
5868
5851
|
},
|
|
5869
5852
|
{
|
|
@@ -5909,7 +5892,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
5909
5892
|
],
|
|
5910
5893
|
"registeredAt": "2026-05-26",
|
|
5911
5894
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.3",
|
|
5912
|
-
"bundledIn": "@cross-deck/web@1.
|
|
5895
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
5913
5896
|
"runtimeVerified": true
|
|
5914
5897
|
},
|
|
5915
5898
|
{
|
|
@@ -6015,7 +5998,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6015
5998
|
],
|
|
6016
5999
|
"registeredAt": "2026-05-26",
|
|
6017
6000
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 2.2.a + 2.2.b + 2.2.c",
|
|
6018
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6001
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6019
6002
|
"runtimeVerified": true
|
|
6020
6003
|
},
|
|
6021
6004
|
{
|
|
@@ -6043,7 +6026,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6043
6026
|
],
|
|
6044
6027
|
"registeredAt": "2026-05-26",
|
|
6045
6028
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 5.5",
|
|
6046
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6029
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6047
6030
|
"runtimeVerified": false
|
|
6048
6031
|
},
|
|
6049
6032
|
{
|
|
@@ -6123,7 +6106,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6123
6106
|
],
|
|
6124
6107
|
"registeredAt": "2026-05-26",
|
|
6125
6108
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 1.3 (web/RN) + dogfood-gap fix (swift + android)",
|
|
6126
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6109
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6127
6110
|
"runtimeVerified": true
|
|
6128
6111
|
},
|
|
6129
6112
|
{
|
|
@@ -6169,7 +6152,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6169
6152
|
],
|
|
6170
6153
|
"registeredAt": "2026-05-26",
|
|
6171
6154
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 6.2",
|
|
6172
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6155
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6173
6156
|
"runtimeVerified": true
|
|
6174
6157
|
},
|
|
6175
6158
|
{
|
|
@@ -6211,7 +6194,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6211
6194
|
],
|
|
6212
6195
|
"registeredAt": "2026-05-26",
|
|
6213
6196
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.2",
|
|
6214
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6197
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6215
6198
|
"runtimeVerified": true
|
|
6216
6199
|
},
|
|
6217
6200
|
{
|
|
@@ -6245,7 +6228,7 @@ var BUNDLED_CONTRACTS = Object.freeze([
|
|
|
6245
6228
|
],
|
|
6246
6229
|
"registeredAt": "2026-05-26",
|
|
6247
6230
|
"firstRegisteredIn": "bank-grade reconciliation v1.4.0 \u2014 phase 3.5",
|
|
6248
|
-
"bundledIn": "@cross-deck/web@1.
|
|
6231
|
+
"bundledIn": "@cross-deck/web@1.7.0",
|
|
6249
6232
|
"runtimeVerified": false
|
|
6250
6233
|
}
|
|
6251
6234
|
]);
|