@drivemetadata-ai/sdk 0.1.1-beta.2 → 0.1.1
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 +152 -21
- package/dist/angular/index.cjs +946 -95
- package/dist/angular/index.cjs.map +1 -1
- package/dist/angular/index.d.cts +2 -2
- package/dist/angular/index.d.ts +2 -2
- package/dist/angular/index.js +946 -95
- package/dist/angular/index.js.map +1 -1
- package/dist/browser/index.cjs +947 -96
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +2 -2
- package/dist/browser/index.d.ts +2 -2
- package/dist/browser/index.js +947 -96
- package/dist/browser/index.js.map +1 -1
- package/dist/next/index.cjs +946 -95
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/index.js +946 -95
- package/dist/next/index.js.map +1 -1
- package/dist/node/index.cjs +81 -9
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +81 -9
- package/dist/node/index.js.map +1 -1
- package/dist/react/index.cjs +946 -95
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +946 -95
- package/dist/react/index.js.map +1 -1
- package/dist/{types--V8TVIqT.d.cts → types-mgbdL1V7.d.cts} +17 -4
- package/dist/{types--V8TVIqT.d.ts → types-mgbdL1V7.d.ts} +17 -4
- package/docs/architecture.md +109 -0
- package/docs/index.md +1 -0
- package/docs/integration.md +203 -5
- package/docs/npm-browser-sdk.md +4 -0
- package/package.json +4 -2
package/dist/browser/index.cjs
CHANGED
|
@@ -37,12 +37,62 @@ __export(browser_exports, {
|
|
|
37
37
|
});
|
|
38
38
|
module.exports = __toCommonJS(browser_exports);
|
|
39
39
|
|
|
40
|
+
// src/browser/core/browser-config.ts
|
|
41
|
+
function setIfDefined(target, key, value) {
|
|
42
|
+
if (value !== void 0) {
|
|
43
|
+
target[key] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function normalizeBrowserConfig(input) {
|
|
47
|
+
const normalized = {
|
|
48
|
+
...input,
|
|
49
|
+
clientId: input.clientId ?? "",
|
|
50
|
+
workspaceId: input.workspaceId ?? "",
|
|
51
|
+
appId: input.appId ?? ""
|
|
52
|
+
};
|
|
53
|
+
setIfDefined(normalized, "apiHost", input.apiHost);
|
|
54
|
+
setIfDefined(normalized, "capturePageview", input.capturePageview);
|
|
55
|
+
setIfDefined(normalized, "capturePageleave", input.capturePageleave);
|
|
56
|
+
setIfDefined(normalized, "captureDeadClicks", input.captureDeadClicks);
|
|
57
|
+
setIfDefined(normalized, "crossSubdomainCookie", input.crossSubdomainCookie);
|
|
58
|
+
setIfDefined(normalized, "sessionIdleTimeoutSeconds", input.sessionIdleTimeoutSeconds);
|
|
59
|
+
setIfDefined(normalized, "schemaValidation", input.schemaValidation);
|
|
60
|
+
setIfDefined(normalized, "beforeSend", input.beforeSend);
|
|
61
|
+
setIfDefined(normalized, "persistence", input.disablePersistence === true ? "none" : input.persistence);
|
|
62
|
+
return normalized;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/core/uuid.ts
|
|
66
|
+
function createUuid() {
|
|
67
|
+
const cryptoApi = globalThis.crypto;
|
|
68
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
69
|
+
return cryptoApi.randomUUID();
|
|
70
|
+
}
|
|
71
|
+
const bytes = new Uint8Array(16);
|
|
72
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
73
|
+
cryptoApi.getRandomValues(bytes);
|
|
74
|
+
} else {
|
|
75
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
76
|
+
bytes[index] = Math.floor(Math.random() * 256);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
80
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
81
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
82
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
83
|
+
}
|
|
84
|
+
function isUuid(value) {
|
|
85
|
+
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
|
86
|
+
}
|
|
87
|
+
function ensureUuid(value) {
|
|
88
|
+
return isUuid(value) ? value : createUuid();
|
|
89
|
+
}
|
|
90
|
+
|
|
40
91
|
// src/core/backend-payload.ts
|
|
41
92
|
function formatUtcTimestamp(value) {
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
return date.toISOString().replace("T", " ").slice(0, 19);
|
|
93
|
+
const date = typeof value === "string" || typeof value === "number" || value instanceof Date ? new Date(value) : /* @__PURE__ */ new Date();
|
|
94
|
+
const safeDate = Number.isNaN(date.getTime()) ? /* @__PURE__ */ new Date() : date;
|
|
95
|
+
return safeDate.toISOString().replace("T", " ").slice(0, 19);
|
|
46
96
|
}
|
|
47
97
|
function cleanObject(value) {
|
|
48
98
|
if (Array.isArray(value)) {
|
|
@@ -73,15 +123,19 @@ function createBackendCollectorPayload(input) {
|
|
|
73
123
|
};
|
|
74
124
|
const metaData = {
|
|
75
125
|
...normalizedEventData,
|
|
76
|
-
requestId: input.requestId,
|
|
126
|
+
requestId: ensureUuid(typeof input.requestId === "string" ? input.requestId : void 0),
|
|
77
127
|
timestamp,
|
|
78
128
|
eventType: input.eventType,
|
|
79
129
|
requestFrom: input.requestFrom ?? "3",
|
|
80
130
|
clientId: input.clientId,
|
|
81
131
|
workspaceId: input.workspaceId,
|
|
82
132
|
token: input.token,
|
|
83
|
-
anonymousId:
|
|
84
|
-
|
|
133
|
+
anonymousId: ensureUuid(
|
|
134
|
+
typeof eventData.anonymousId === "string" ? eventData.anonymousId : typeof input.anonymousId === "string" ? input.anonymousId : void 0
|
|
135
|
+
),
|
|
136
|
+
sessionId: ensureUuid(
|
|
137
|
+
typeof eventData.sessionId === "string" ? eventData.sessionId : typeof input.sessionId === "string" ? input.sessionId : void 0
|
|
138
|
+
),
|
|
85
139
|
ua: input.ua,
|
|
86
140
|
appDetails: { app_id: input.appId },
|
|
87
141
|
page: { ...page2, url: page2.url ?? input.pageUrl },
|
|
@@ -92,12 +146,45 @@ function createBackendCollectorPayload(input) {
|
|
|
92
146
|
return cleanObject(payload);
|
|
93
147
|
}
|
|
94
148
|
|
|
95
|
-
// src/core/
|
|
96
|
-
|
|
97
|
-
|
|
149
|
+
// src/core/backend-schema.ts
|
|
150
|
+
var requiredMetaDataFields = [
|
|
151
|
+
"requestId",
|
|
152
|
+
"timestamp",
|
|
153
|
+
"eventType",
|
|
154
|
+
"requestFrom",
|
|
155
|
+
"clientId",
|
|
156
|
+
"workspaceId",
|
|
157
|
+
"anonymousId",
|
|
158
|
+
"sessionId"
|
|
159
|
+
];
|
|
160
|
+
function isPresent(value) {
|
|
161
|
+
return value !== null && value !== void 0 && value !== "";
|
|
162
|
+
}
|
|
163
|
+
function validateBackendCollectorPayload(payload) {
|
|
164
|
+
const errors = [];
|
|
165
|
+
const metaData = payload.metaData;
|
|
166
|
+
if (!metaData || typeof metaData !== "object" || Array.isArray(metaData)) {
|
|
167
|
+
return {
|
|
168
|
+
ok: false,
|
|
169
|
+
errors: ["metaData is required"]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const metadataRecord = metaData;
|
|
173
|
+
for (const field of requiredMetaDataFields) {
|
|
174
|
+
if (!isPresent(metadataRecord[field])) {
|
|
175
|
+
errors.push(`metaData.${field} is required`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (isPresent(metadataRecord.eventType) && typeof metadataRecord.eventType !== "string") {
|
|
179
|
+
errors.push("metaData.eventType must be a string");
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
ok: errors.length === 0,
|
|
183
|
+
errors
|
|
184
|
+
};
|
|
98
185
|
}
|
|
99
186
|
|
|
100
|
-
// src/
|
|
187
|
+
// src/core/consent.ts
|
|
101
188
|
var purposes = [
|
|
102
189
|
"analytics",
|
|
103
190
|
"advertising",
|
|
@@ -137,6 +224,476 @@ function canCollectPurpose(consent2, purpose) {
|
|
|
137
224
|
return consent2[purpose] === "granted";
|
|
138
225
|
}
|
|
139
226
|
|
|
227
|
+
// src/core/event-schema.ts
|
|
228
|
+
var reservedKeys = /* @__PURE__ */ new Set(["messageId", "timestamp", "type", "event", "anonymousId", "userId", "context"]);
|
|
229
|
+
function validateEventEnvelope(envelope, options = {}) {
|
|
230
|
+
if (options.mode === "off") return { ok: true, errors: [] };
|
|
231
|
+
const errors = [];
|
|
232
|
+
if (typeof envelope.type !== "string") errors.push("type must be a string");
|
|
233
|
+
if (envelope.type === "track" && typeof envelope.event !== "string") {
|
|
234
|
+
errors.push("track event must include event name");
|
|
235
|
+
}
|
|
236
|
+
if (typeof envelope.messageId !== "string") errors.push("messageId must be a string");
|
|
237
|
+
if (typeof envelope.timestamp !== "string") errors.push("timestamp must be an ISO string");
|
|
238
|
+
for (const key of Object.keys(envelope.properties ?? {})) {
|
|
239
|
+
if (reservedKeys.has(key)) errors.push(`properties.${key} is reserved`);
|
|
240
|
+
}
|
|
241
|
+
return { ok: errors.length === 0, errors };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// src/core/environment.ts
|
|
245
|
+
function getBrowserWindow() {
|
|
246
|
+
return typeof window === "undefined" ? void 0 : window;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/core/privacy.ts
|
|
250
|
+
var sensitiveKeys = /* @__PURE__ */ new Set([
|
|
251
|
+
"email",
|
|
252
|
+
"phone",
|
|
253
|
+
"mobile",
|
|
254
|
+
"address",
|
|
255
|
+
"address1",
|
|
256
|
+
"address2",
|
|
257
|
+
"first_name",
|
|
258
|
+
"last_name",
|
|
259
|
+
"name",
|
|
260
|
+
"token",
|
|
261
|
+
"secret",
|
|
262
|
+
"password",
|
|
263
|
+
"session",
|
|
264
|
+
"cookie"
|
|
265
|
+
]);
|
|
266
|
+
function redactUrl(url, allowQueryKeys = ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
|
|
267
|
+
const parsed = new URL(url, "https://placeholder.local");
|
|
268
|
+
for (const key of Array.from(parsed.searchParams.keys())) {
|
|
269
|
+
if (!allowQueryKeys.includes(key)) {
|
|
270
|
+
parsed.searchParams.set(key, "[REDACTED]");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return url.startsWith("http") ? parsed.toString() : `${parsed.pathname}${parsed.search}`;
|
|
274
|
+
}
|
|
275
|
+
function sanitizeValue(value, allow, path = []) {
|
|
276
|
+
if (Array.isArray(value)) {
|
|
277
|
+
return value.map((item) => sanitizeValue(item, allow, path));
|
|
278
|
+
}
|
|
279
|
+
if (value && typeof value === "object") {
|
|
280
|
+
return Object.fromEntries(
|
|
281
|
+
Object.entries(value).filter(([key]) => {
|
|
282
|
+
const lowerKey = key.toLowerCase();
|
|
283
|
+
const lowerPath = path.map((item) => item.toLowerCase());
|
|
284
|
+
const isEcommerceItemName = lowerKey === "name" && lowerPath.includes("ecommerce") && lowerPath.includes("items");
|
|
285
|
+
return isEcommerceItemName || !sensitiveKeys.has(lowerKey) || allow.has(lowerKey);
|
|
286
|
+
}).map(([key, nestedValue]) => [key, sanitizeValue(nestedValue, allow, [...path, key])])
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
return value;
|
|
290
|
+
}
|
|
291
|
+
function sanitizeProperties(input, allowRawKeys = []) {
|
|
292
|
+
const allow = new Set(allowRawKeys.map((key) => key.toLowerCase()));
|
|
293
|
+
return sanitizeValue(input, allow);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/browser/core/attribute-persistence.ts
|
|
297
|
+
var DMD_ATTRIBUTES_STORAGE_KEY = "dmd_attributes";
|
|
298
|
+
var SESSION_STORAGE_KEY = "sessionData";
|
|
299
|
+
var SESSION_ID_KEY = "sessionId";
|
|
300
|
+
var SESSION_TIMESTAMP_KEY = "timestamp";
|
|
301
|
+
function isBlankValue(value) {
|
|
302
|
+
return value === null || value === void 0 || typeof value === "string" && value.trim() === "";
|
|
303
|
+
}
|
|
304
|
+
function readAttributes(base) {
|
|
305
|
+
const raw = base.getItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
306
|
+
if (!raw) return {};
|
|
307
|
+
try {
|
|
308
|
+
const parsed = JSON.parse(raw);
|
|
309
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
310
|
+
} catch {
|
|
311
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
312
|
+
return {};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function sanitizeAttributes(attributes) {
|
|
316
|
+
return Object.fromEntries(Object.entries(attributes).filter(([, value]) => !isBlankValue(value)));
|
|
317
|
+
}
|
|
318
|
+
function writeAttributes(base, attributes) {
|
|
319
|
+
const sanitized = sanitizeAttributes(attributes);
|
|
320
|
+
if (Object.keys(sanitized).length === 0) {
|
|
321
|
+
base.removeItem(DMD_ATTRIBUTES_STORAGE_KEY);
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
base.setItem(DMD_ATTRIBUTES_STORAGE_KEY, JSON.stringify(sanitized));
|
|
325
|
+
}
|
|
326
|
+
function parseSessionData(value) {
|
|
327
|
+
try {
|
|
328
|
+
const parsed = JSON.parse(value);
|
|
329
|
+
const sessionData = {};
|
|
330
|
+
const sessionId = typeof parsed.sessionId === "string" && parsed.sessionId.trim() !== "" ? parsed.sessionId : void 0;
|
|
331
|
+
const timestamp = typeof parsed.timestamp === "number" ? parsed.timestamp : void 0;
|
|
332
|
+
if (sessionId !== void 0) sessionData.sessionId = sessionId;
|
|
333
|
+
if (timestamp !== void 0) sessionData.timestamp = timestamp;
|
|
334
|
+
return sessionData;
|
|
335
|
+
} catch {
|
|
336
|
+
return {};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
function getAggregateValue(attributes, key) {
|
|
340
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
341
|
+
const sessionId = attributes[SESSION_ID_KEY];
|
|
342
|
+
const timestamp = attributes[SESSION_TIMESTAMP_KEY];
|
|
343
|
+
if (typeof sessionId === "string" && !isBlankValue(sessionId) && typeof timestamp === "number") {
|
|
344
|
+
return JSON.stringify({ sessionId, timestamp });
|
|
345
|
+
}
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
const value = attributes[key];
|
|
349
|
+
if (isBlankValue(value)) return null;
|
|
350
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
351
|
+
}
|
|
352
|
+
function setAggregateValue(attributes, key, value) {
|
|
353
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
354
|
+
const sessionData = parseSessionData(value);
|
|
355
|
+
if (sessionData.sessionId === void 0 || sessionData.timestamp === void 0) {
|
|
356
|
+
delete attributes[SESSION_ID_KEY];
|
|
357
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
attributes[SESSION_ID_KEY] = sessionData.sessionId;
|
|
361
|
+
attributes[SESSION_TIMESTAMP_KEY] = sessionData.timestamp;
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
attributes[key] = value;
|
|
365
|
+
}
|
|
366
|
+
function removeAggregateValue(attributes, key) {
|
|
367
|
+
if (key === SESSION_STORAGE_KEY) {
|
|
368
|
+
delete attributes[SESSION_ID_KEY];
|
|
369
|
+
delete attributes[SESSION_TIMESTAMP_KEY];
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
delete attributes[key];
|
|
373
|
+
}
|
|
374
|
+
function createDmdAttributesPersistence(base) {
|
|
375
|
+
return {
|
|
376
|
+
getItem(key) {
|
|
377
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.getItem(key);
|
|
378
|
+
const attributes = readAttributes(base);
|
|
379
|
+
const aggregateValue = getAggregateValue(attributes, key);
|
|
380
|
+
if (aggregateValue !== null) return aggregateValue;
|
|
381
|
+
const legacyValue = base.getItem(key);
|
|
382
|
+
if (isBlankValue(legacyValue)) return null;
|
|
383
|
+
setAggregateValue(attributes, key, String(legacyValue));
|
|
384
|
+
writeAttributes(base, attributes);
|
|
385
|
+
return legacyValue;
|
|
386
|
+
},
|
|
387
|
+
setItem(key, value) {
|
|
388
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) return base.setItem(key, value);
|
|
389
|
+
const attributes = readAttributes(base);
|
|
390
|
+
if (isBlankValue(value)) {
|
|
391
|
+
removeAggregateValue(attributes, key);
|
|
392
|
+
writeAttributes(base, attributes);
|
|
393
|
+
base.removeItem(key);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
setAggregateValue(attributes, key, value);
|
|
397
|
+
writeAttributes(base, attributes);
|
|
398
|
+
base.setItem(key, value);
|
|
399
|
+
return true;
|
|
400
|
+
},
|
|
401
|
+
removeItem(key) {
|
|
402
|
+
if (key === DMD_ATTRIBUTES_STORAGE_KEY) {
|
|
403
|
+
base.removeItem(key);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const attributes = readAttributes(base);
|
|
407
|
+
removeAggregateValue(attributes, key);
|
|
408
|
+
writeAttributes(base, attributes);
|
|
409
|
+
base.removeItem(key);
|
|
410
|
+
},
|
|
411
|
+
getHealth() {
|
|
412
|
+
return base.getHealth();
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// src/core/attribution.ts
|
|
418
|
+
var dmdUtmKeys = [
|
|
419
|
+
"utm_source",
|
|
420
|
+
"utm_medium",
|
|
421
|
+
"utm_campaign",
|
|
422
|
+
"utm_term",
|
|
423
|
+
"utm_content",
|
|
424
|
+
"utm_id"
|
|
425
|
+
];
|
|
426
|
+
var dmdCampaignKeys = ["campaign_id", "ad_id"];
|
|
427
|
+
var dmdClickIdSources = [
|
|
428
|
+
["gclid", 2],
|
|
429
|
+
["fbclid", 3],
|
|
430
|
+
["ScCid", 1],
|
|
431
|
+
["li_fat_id", 4]
|
|
432
|
+
];
|
|
433
|
+
function cleanAttributionRecord(record) {
|
|
434
|
+
const cleaned = Object.fromEntries(
|
|
435
|
+
Object.entries(record).filter(([, value]) => value !== null && value !== void 0 && value !== "")
|
|
436
|
+
);
|
|
437
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
438
|
+
}
|
|
439
|
+
function objectValue(value) {
|
|
440
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
441
|
+
}
|
|
442
|
+
function mergeAttributionRecords(explicitProperties, stored) {
|
|
443
|
+
const attributionData = objectValue(explicitProperties.attributionData);
|
|
444
|
+
const utmParameter = objectValue(explicitProperties.utmParameter);
|
|
445
|
+
return {
|
|
446
|
+
...explicitProperties,
|
|
447
|
+
...stored.attributionData || attributionData ? { attributionData: { ...stored.attributionData ?? {}, ...attributionData ?? {} } } : {},
|
|
448
|
+
...stored.utmParameter || utmParameter ? { utmParameter: { ...stored.utmParameter ?? {}, ...utmParameter ?? {} } } : {}
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/browser/core/attribution.ts
|
|
453
|
+
var DMD_CLICK_ID_QUERY_KEY = "click_id";
|
|
454
|
+
var DMD_CLICK_ID_LEGACY_QUERY_KEY = "dmd_click_id";
|
|
455
|
+
var DMD_CLICK_ID_STORAGE_KEY = "dmd_click_id";
|
|
456
|
+
var DMD_CLICK_ID_ATTRIBUTE_KEY = "click_id";
|
|
457
|
+
function getCurrentUrl() {
|
|
458
|
+
return getBrowserWindow()?.location?.href;
|
|
459
|
+
}
|
|
460
|
+
function getCookie(name) {
|
|
461
|
+
const cookie = getBrowserWindow()?.document?.cookie;
|
|
462
|
+
if (!cookie) return void 0;
|
|
463
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
464
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
465
|
+
return match ? decodeURIComponent(match[1] ?? "") : void 0;
|
|
466
|
+
}
|
|
467
|
+
function getParams(url) {
|
|
468
|
+
return new URL(url, "https://placeholder.local").searchParams;
|
|
469
|
+
}
|
|
470
|
+
function setIfPresent(persistence, key, value) {
|
|
471
|
+
if (value !== null && value !== "") {
|
|
472
|
+
persistence.setItem(key, value);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
function getClickIdParam(params) {
|
|
476
|
+
return params.get(DMD_CLICK_ID_LEGACY_QUERY_KEY) || params.get(DMD_CLICK_ID_QUERY_KEY);
|
|
477
|
+
}
|
|
478
|
+
function getStoredString(persistence, key) {
|
|
479
|
+
const value = persistence.getItem(key);
|
|
480
|
+
return value === null || value === "" ? void 0 : value;
|
|
481
|
+
}
|
|
482
|
+
function getStoredNumberOrString(persistence, key) {
|
|
483
|
+
const value = getStoredString(persistence, key);
|
|
484
|
+
if (value === void 0) return void 0;
|
|
485
|
+
const parsed = Number.parseInt(value, 10);
|
|
486
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
487
|
+
}
|
|
488
|
+
function captureAttributionFromUrl(persistence, url = getCurrentUrl()) {
|
|
489
|
+
if (!url) return;
|
|
490
|
+
const params = getParams(url);
|
|
491
|
+
for (const key of dmdUtmKeys) {
|
|
492
|
+
setIfPresent(persistence, key, params.get(key));
|
|
493
|
+
}
|
|
494
|
+
for (const key of dmdCampaignKeys) {
|
|
495
|
+
setIfPresent(persistence, key, params.get(key));
|
|
496
|
+
}
|
|
497
|
+
const clickId = getClickIdParam(params);
|
|
498
|
+
setIfPresent(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY, clickId);
|
|
499
|
+
setIfPresent(persistence, DMD_CLICK_ID_STORAGE_KEY, clickId);
|
|
500
|
+
for (const [param, sdkPubId] of dmdClickIdSources) {
|
|
501
|
+
const value = params.get(param);
|
|
502
|
+
if (value) {
|
|
503
|
+
persistence.setItem("unique_id", value);
|
|
504
|
+
persistence.setItem("sdk_pub_id", String(sdkPubId));
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
function getStoredAttributionData(persistence) {
|
|
509
|
+
return cleanAttributionRecord({
|
|
510
|
+
unique_id: getStoredString(persistence, "unique_id"),
|
|
511
|
+
sdk_pub_id: getStoredNumberOrString(persistence, "sdk_pub_id"),
|
|
512
|
+
fbc: getStoredString(persistence, "fbc") ?? getCookie("_fbc"),
|
|
513
|
+
fbp: getStoredString(persistence, "fbp") ?? getCookie("_fbp"),
|
|
514
|
+
campaign_id: getStoredString(persistence, "campaign_id"),
|
|
515
|
+
ad_id: getStoredString(persistence, "ad_id"),
|
|
516
|
+
click_id: getStoredString(persistence, DMD_CLICK_ID_STORAGE_KEY) ?? getStoredString(persistence, DMD_CLICK_ID_ATTRIBUTE_KEY)
|
|
517
|
+
});
|
|
518
|
+
}
|
|
519
|
+
function getStoredUtmParameter(persistence) {
|
|
520
|
+
return cleanAttributionRecord(Object.fromEntries(dmdUtmKeys.map((key) => [key, getStoredString(persistence, key)])));
|
|
521
|
+
}
|
|
522
|
+
function mergeStoredAttribution(properties, persistence) {
|
|
523
|
+
const stored = {};
|
|
524
|
+
const attributionData = getStoredAttributionData(persistence);
|
|
525
|
+
const utmParameter = getStoredUtmParameter(persistence);
|
|
526
|
+
if (attributionData !== void 0) stored.attributionData = attributionData;
|
|
527
|
+
if (utmParameter !== void 0) stored.utmParameter = utmParameter;
|
|
528
|
+
return mergeAttributionRecords(properties, stored);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// src/browser/core/autocapture.ts
|
|
532
|
+
function installAutocapture(config) {
|
|
533
|
+
const trackedPageUrls = /* @__PURE__ */ new Set();
|
|
534
|
+
const timers = /* @__PURE__ */ new Set();
|
|
535
|
+
const pageviewDelayMs = config.pageviewDelayMs ?? 500;
|
|
536
|
+
const history = config.browserWindow.history;
|
|
537
|
+
const originalPushState = history?.pushState;
|
|
538
|
+
const originalReplaceState = history?.replaceState;
|
|
539
|
+
function clearTimer(timer) {
|
|
540
|
+
timers.delete(timer);
|
|
541
|
+
clearTimeout(timer);
|
|
542
|
+
}
|
|
543
|
+
function canonicalUrl() {
|
|
544
|
+
return config.browserWindow.location.href;
|
|
545
|
+
}
|
|
546
|
+
function trackCurrentPageview() {
|
|
547
|
+
if (!config.capturePageview) return;
|
|
548
|
+
const url = canonicalUrl();
|
|
549
|
+
if (trackedPageUrls.has(url)) return;
|
|
550
|
+
trackedPageUrls.add(url);
|
|
551
|
+
config.onPageView();
|
|
552
|
+
}
|
|
553
|
+
function schedulePageview(delayMs) {
|
|
554
|
+
if (!config.capturePageview) return;
|
|
555
|
+
const timer = setTimeout(() => {
|
|
556
|
+
timers.delete(timer);
|
|
557
|
+
trackCurrentPageview();
|
|
558
|
+
}, delayMs);
|
|
559
|
+
timers.add(timer);
|
|
560
|
+
}
|
|
561
|
+
function handleRouteChange() {
|
|
562
|
+
config.onRouteChange?.();
|
|
563
|
+
trackCurrentPageview();
|
|
564
|
+
}
|
|
565
|
+
function wrapHistoryMethod(method) {
|
|
566
|
+
if (!history) return;
|
|
567
|
+
const original = history[method];
|
|
568
|
+
if (typeof original !== "function") return;
|
|
569
|
+
history[method] = function wrappedHistoryMethod(...args) {
|
|
570
|
+
const result = original.apply(this, args);
|
|
571
|
+
const timer = setTimeout(() => {
|
|
572
|
+
timers.delete(timer);
|
|
573
|
+
handleRouteChange();
|
|
574
|
+
}, 0);
|
|
575
|
+
timers.add(timer);
|
|
576
|
+
return result;
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
function handlePopOrHashChange() {
|
|
580
|
+
handleRouteChange();
|
|
581
|
+
}
|
|
582
|
+
function handlePageLeave() {
|
|
583
|
+
if (config.capturePageleave) {
|
|
584
|
+
config.onPageLeave();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
schedulePageview(pageviewDelayMs);
|
|
588
|
+
wrapHistoryMethod("pushState");
|
|
589
|
+
wrapHistoryMethod("replaceState");
|
|
590
|
+
const canListen = typeof config.browserWindow.addEventListener === "function" && typeof config.browserWindow.removeEventListener === "function";
|
|
591
|
+
if (canListen) {
|
|
592
|
+
config.browserWindow.addEventListener("popstate", handlePopOrHashChange);
|
|
593
|
+
config.browserWindow.addEventListener("hashchange", handlePopOrHashChange);
|
|
594
|
+
config.browserWindow.addEventListener("beforeunload", handlePageLeave);
|
|
595
|
+
}
|
|
596
|
+
return {
|
|
597
|
+
cleanup() {
|
|
598
|
+
for (const timer of Array.from(timers)) {
|
|
599
|
+
clearTimer(timer);
|
|
600
|
+
}
|
|
601
|
+
if (history && originalPushState) history.pushState = originalPushState;
|
|
602
|
+
if (history && originalReplaceState) history.replaceState = originalReplaceState;
|
|
603
|
+
if (canListen) {
|
|
604
|
+
config.browserWindow.removeEventListener("popstate", handlePopOrHashChange);
|
|
605
|
+
config.browserWindow.removeEventListener("hashchange", handlePopOrHashChange);
|
|
606
|
+
config.browserWindow.removeEventListener("beforeunload", handlePageLeave);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// src/core/payload-size.ts
|
|
613
|
+
var preserveStringKeys = /* @__PURE__ */ new Set([
|
|
614
|
+
"requestId",
|
|
615
|
+
"eventType",
|
|
616
|
+
"requestFrom",
|
|
617
|
+
"clientId",
|
|
618
|
+
"workspaceId",
|
|
619
|
+
"anonymousId",
|
|
620
|
+
"sessionId",
|
|
621
|
+
"token"
|
|
622
|
+
]);
|
|
623
|
+
function payloadByteLength(payload) {
|
|
624
|
+
const serialized = JSON.stringify(payload);
|
|
625
|
+
if (typeof TextEncoder !== "undefined") {
|
|
626
|
+
return new TextEncoder().encode(serialized).length;
|
|
627
|
+
}
|
|
628
|
+
return serialized.length;
|
|
629
|
+
}
|
|
630
|
+
function clonePayload(payload) {
|
|
631
|
+
try {
|
|
632
|
+
return JSON.parse(JSON.stringify(payload));
|
|
633
|
+
} catch {
|
|
634
|
+
return void 0;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
function truncateValue(value, truncateStringLength, key) {
|
|
638
|
+
if (typeof value === "string") {
|
|
639
|
+
if (key && preserveStringKeys.has(key)) return value;
|
|
640
|
+
if (value.length <= truncateStringLength) return value;
|
|
641
|
+
return `${value.slice(0, truncateStringLength)}...[TRUNCATED]`;
|
|
642
|
+
}
|
|
643
|
+
if (Array.isArray(value)) {
|
|
644
|
+
return value.map((item) => truncateValue(item, truncateStringLength));
|
|
645
|
+
}
|
|
646
|
+
if (value && typeof value === "object") {
|
|
647
|
+
return Object.fromEntries(
|
|
648
|
+
Object.entries(value).map(([childKey, childValue]) => [
|
|
649
|
+
childKey,
|
|
650
|
+
truncateValue(childValue, truncateStringLength, childKey)
|
|
651
|
+
])
|
|
652
|
+
);
|
|
653
|
+
}
|
|
654
|
+
return value;
|
|
655
|
+
}
|
|
656
|
+
function markPayloadTruncated(payload) {
|
|
657
|
+
if (payload.metaData && typeof payload.metaData === "object" && !Array.isArray(payload.metaData)) {
|
|
658
|
+
return {
|
|
659
|
+
...payload,
|
|
660
|
+
metaData: {
|
|
661
|
+
...payload.metaData,
|
|
662
|
+
payloadTruncated: true
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
return {
|
|
667
|
+
...payload,
|
|
668
|
+
payloadTruncated: true
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
function truncatePayload(payload, truncateStringLength) {
|
|
672
|
+
const cloned = clonePayload(payload);
|
|
673
|
+
if (!cloned) return void 0;
|
|
674
|
+
return markPayloadTruncated(truncateValue(cloned, truncateStringLength));
|
|
675
|
+
}
|
|
676
|
+
function getPayloadMessageId(payload) {
|
|
677
|
+
const value = payload.metaData?.requestId ?? payload.messageId;
|
|
678
|
+
return value === void 0 ? void 0 : String(value);
|
|
679
|
+
}
|
|
680
|
+
function preparePayloadForSizePolicy(payload, options = {}) {
|
|
681
|
+
const maxPayloadBytes = options.maxPayloadBytes ?? 64e3;
|
|
682
|
+
const payloadSizePolicy = options.payloadSizePolicy ?? "drop";
|
|
683
|
+
const payloadTruncateStringLength = options.payloadTruncateStringLength ?? 1024;
|
|
684
|
+
if (payloadByteLength(payload) <= maxPayloadBytes) {
|
|
685
|
+
return { ok: true, payload, truncated: false };
|
|
686
|
+
}
|
|
687
|
+
if (payloadSizePolicy === "truncate") {
|
|
688
|
+
const truncatedPayload = truncatePayload(payload, payloadTruncateStringLength);
|
|
689
|
+
if (truncatedPayload && payloadByteLength(truncatedPayload) <= maxPayloadBytes) {
|
|
690
|
+
return { ok: true, payload: truncatedPayload, truncated: true };
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
const messageId = getPayloadMessageId(payload);
|
|
694
|
+
return messageId === void 0 ? { ok: false, reason: "payload_too_large" } : { ok: false, reason: "payload_too_large", messageId };
|
|
695
|
+
}
|
|
696
|
+
|
|
140
697
|
// src/browser/core/delivery.ts
|
|
141
698
|
function createId(prefix) {
|
|
142
699
|
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
@@ -168,7 +725,6 @@ function createDeliveryManager(config) {
|
|
|
168
725
|
const lockTtlMs = config.lockTtlMs ?? 5e3;
|
|
169
726
|
const tabId = config.tabId ?? createId("tab");
|
|
170
727
|
const batchSize = config.batchSize ?? 25;
|
|
171
|
-
const maxPayloadBytes = config.maxPayloadBytes ?? 64e3;
|
|
172
728
|
function recordDrop(event) {
|
|
173
729
|
diagnostics.dropped.push(event);
|
|
174
730
|
config.onDrop?.(event);
|
|
@@ -177,12 +733,22 @@ function createDeliveryManager(config) {
|
|
|
177
733
|
diagnostics.lastError = error.message;
|
|
178
734
|
config.onError?.(error);
|
|
179
735
|
}
|
|
180
|
-
function
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
183
|
-
|
|
736
|
+
function preparePayloadForSend(payload) {
|
|
737
|
+
const sizePolicyOptions = {};
|
|
738
|
+
if (config.maxPayloadBytes !== void 0) sizePolicyOptions.maxPayloadBytes = config.maxPayloadBytes;
|
|
739
|
+
if (config.payloadSizePolicy !== void 0) sizePolicyOptions.payloadSizePolicy = config.payloadSizePolicy;
|
|
740
|
+
if (config.payloadTruncateStringLength !== void 0) {
|
|
741
|
+
sizePolicyOptions.payloadTruncateStringLength = config.payloadTruncateStringLength;
|
|
184
742
|
}
|
|
185
|
-
|
|
743
|
+
const prepared = preparePayloadForSizePolicy(payload, sizePolicyOptions);
|
|
744
|
+
if (prepared.ok) return prepared.payload;
|
|
745
|
+
const diagnostic = {
|
|
746
|
+
reason: prepared.reason,
|
|
747
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
748
|
+
};
|
|
749
|
+
if (prepared.messageId !== void 0) diagnostic.messageId = prepared.messageId;
|
|
750
|
+
recordDrop(diagnostic);
|
|
751
|
+
return void 0;
|
|
186
752
|
}
|
|
187
753
|
function recordStorageUnavailable() {
|
|
188
754
|
recordDrop({
|
|
@@ -272,7 +838,19 @@ function createDeliveryManager(config) {
|
|
|
272
838
|
idempotencyKey: String(payload.idempotencyKey ?? createIdempotencyKey(payload, messageId))
|
|
273
839
|
};
|
|
274
840
|
}
|
|
841
|
+
function tryBeacon(body) {
|
|
842
|
+
if (!config.useBeacon) return false;
|
|
843
|
+
const sendBeacon = globalThis.navigator?.sendBeacon;
|
|
844
|
+
if (typeof sendBeacon !== "function") return false;
|
|
845
|
+
try {
|
|
846
|
+
const blob = new Blob([JSON.stringify(body)], { type: "application/json" });
|
|
847
|
+
return sendBeacon.call(globalThis.navigator, config.endpoint, blob);
|
|
848
|
+
} catch {
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
275
852
|
async function deliver(body) {
|
|
853
|
+
if (tryBeacon(body)) return;
|
|
276
854
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
277
855
|
if (typeof fetchImpl !== "function") {
|
|
278
856
|
throw new Error("fetch_unavailable");
|
|
@@ -289,26 +867,22 @@ function createDeliveryManager(config) {
|
|
|
289
867
|
return {
|
|
290
868
|
async send(payload) {
|
|
291
869
|
const body = withEnvelope(payload);
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
messageId: String(body.metaData?.requestId ?? body.messageId),
|
|
295
|
-
reason: "payload_too_large",
|
|
296
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
297
|
-
});
|
|
870
|
+
const preparedBody = preparePayloadForSend(body);
|
|
871
|
+
if (!preparedBody) {
|
|
298
872
|
return;
|
|
299
873
|
}
|
|
300
874
|
diagnostics.inFlight += 1;
|
|
301
875
|
try {
|
|
302
|
-
await deliver(
|
|
876
|
+
await deliver(preparedBody);
|
|
303
877
|
} catch (error) {
|
|
304
878
|
const deliveryError = error instanceof Error ? error : new Error(String(error));
|
|
305
879
|
recordError(deliveryError);
|
|
306
880
|
enqueue({
|
|
307
|
-
messageId: String(body
|
|
881
|
+
messageId: String(getPayloadMessageId(body)),
|
|
308
882
|
savedAt: Date.now(),
|
|
309
883
|
attempts: 1,
|
|
310
884
|
lastError: deliveryError.message,
|
|
311
|
-
payload:
|
|
885
|
+
payload: preparedBody
|
|
312
886
|
});
|
|
313
887
|
} finally {
|
|
314
888
|
diagnostics.inFlight -= 1;
|
|
@@ -421,60 +995,286 @@ function createDeliveryManager(config) {
|
|
|
421
995
|
};
|
|
422
996
|
}
|
|
423
997
|
|
|
424
|
-
// src/browser/core/
|
|
425
|
-
var
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
"name",
|
|
435
|
-
"token",
|
|
436
|
-
"secret",
|
|
437
|
-
"password",
|
|
438
|
-
"session",
|
|
439
|
-
"cookie"
|
|
440
|
-
]);
|
|
441
|
-
function sanitizeValue(value, allow) {
|
|
442
|
-
if (Array.isArray(value)) {
|
|
443
|
-
return value.map((item) => sanitizeValue(item, allow));
|
|
998
|
+
// src/browser/core/identity.ts
|
|
999
|
+
var ANONYMOUS_ID_STORAGE_KEY = "dmd_anonymous_id";
|
|
1000
|
+
var LEGACY_ANONYMOUS_ID_STORAGE_KEY = "anonymousId";
|
|
1001
|
+
function getUrlParam(name) {
|
|
1002
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1003
|
+
if (!href) return null;
|
|
1004
|
+
try {
|
|
1005
|
+
return new URL(href).searchParams.get(name);
|
|
1006
|
+
} catch {
|
|
1007
|
+
return null;
|
|
444
1008
|
}
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
1009
|
+
}
|
|
1010
|
+
function resolveAnonymousId(persistence) {
|
|
1011
|
+
const urlAnonymousId = getUrlParam("aid");
|
|
1012
|
+
if (isUuid(urlAnonymousId)) {
|
|
1013
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, urlAnonymousId);
|
|
1014
|
+
return urlAnonymousId;
|
|
449
1015
|
}
|
|
450
|
-
|
|
1016
|
+
const storedAnonymousId = persistence.getItem(ANONYMOUS_ID_STORAGE_KEY);
|
|
1017
|
+
if (isUuid(storedAnonymousId)) {
|
|
1018
|
+
return storedAnonymousId;
|
|
1019
|
+
}
|
|
1020
|
+
const legacyAnonymousId = persistence.getItem(LEGACY_ANONYMOUS_ID_STORAGE_KEY);
|
|
1021
|
+
if (isUuid(legacyAnonymousId)) {
|
|
1022
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, legacyAnonymousId);
|
|
1023
|
+
return legacyAnonymousId;
|
|
1024
|
+
}
|
|
1025
|
+
const anonymousId = createUuid();
|
|
1026
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1027
|
+
return anonymousId;
|
|
451
1028
|
}
|
|
452
|
-
function
|
|
453
|
-
const
|
|
454
|
-
|
|
1029
|
+
function resetAnonymousId(persistence) {
|
|
1030
|
+
const anonymousId = createUuid();
|
|
1031
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
1032
|
+
return anonymousId;
|
|
455
1033
|
}
|
|
456
1034
|
|
|
457
|
-
// src/browser/core/
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
1035
|
+
// src/browser/core/page-context.ts
|
|
1036
|
+
function redactSearch(search) {
|
|
1037
|
+
const redacted = redactUrl(search);
|
|
1038
|
+
return redacted.startsWith("/?") ? redacted.slice(1) : redacted;
|
|
1039
|
+
}
|
|
1040
|
+
function getBrowserPageContext() {
|
|
1041
|
+
const browserWindow = getBrowserWindow();
|
|
1042
|
+
const documentRef = browserWindow?.document ?? globalThis.document;
|
|
1043
|
+
const location = browserWindow?.location;
|
|
1044
|
+
const page2 = {};
|
|
1045
|
+
if (location?.href) page2.url = location.href;
|
|
1046
|
+
if (location?.pathname) page2.path = location.pathname;
|
|
1047
|
+
if (location?.search) page2.search = redactSearch(location.search);
|
|
1048
|
+
if (documentRef?.title) page2.title = documentRef.title;
|
|
1049
|
+
if (documentRef?.referrer) page2.referrer = redactUrl(documentRef.referrer);
|
|
1050
|
+
return page2;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// src/browser/core/persistence.ts
|
|
1054
|
+
function createPersistenceHealth(requested) {
|
|
1055
|
+
return {
|
|
1056
|
+
requested,
|
|
1057
|
+
cookieFallbackUsed: false,
|
|
1058
|
+
memoryFallbackUsed: requested === "memory",
|
|
1059
|
+
failures: []
|
|
1060
|
+
};
|
|
1061
|
+
}
|
|
1062
|
+
function recordFailure(health, backend, operation, error) {
|
|
1063
|
+
health.failures.push({
|
|
1064
|
+
backend,
|
|
1065
|
+
operation,
|
|
1066
|
+
message: error instanceof Error ? error.message : String(error)
|
|
1067
|
+
});
|
|
1068
|
+
if (health.failures.length > 25) {
|
|
1069
|
+
health.failures.shift();
|
|
465
1070
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
1071
|
+
}
|
|
1072
|
+
function createMemoryPersistence(health = createPersistenceHealth("memory")) {
|
|
1073
|
+
const memory = {};
|
|
1074
|
+
return {
|
|
1075
|
+
getItem(key) {
|
|
1076
|
+
return Object.prototype.hasOwnProperty.call(memory, key) ? memory[key] ?? null : null;
|
|
1077
|
+
},
|
|
1078
|
+
setItem(key, value) {
|
|
1079
|
+
memory[key] = value;
|
|
1080
|
+
return true;
|
|
1081
|
+
},
|
|
1082
|
+
removeItem(key) {
|
|
1083
|
+
delete memory[key];
|
|
1084
|
+
},
|
|
1085
|
+
getHealth() {
|
|
1086
|
+
return {
|
|
1087
|
+
...health,
|
|
1088
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
function getCookie2(name) {
|
|
1094
|
+
const browserWindow = getBrowserWindow();
|
|
1095
|
+
const cookie = browserWindow?.document?.cookie;
|
|
1096
|
+
if (!cookie) return null;
|
|
1097
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1098
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
1099
|
+
return match ? decodeURIComponent(match[1] ?? "") : null;
|
|
1100
|
+
}
|
|
1101
|
+
function setCookie(name, value) {
|
|
1102
|
+
const browserWindow = getBrowserWindow();
|
|
1103
|
+
if (!browserWindow?.document) return false;
|
|
1104
|
+
try {
|
|
1105
|
+
const expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toUTCString();
|
|
1106
|
+
const secure = browserWindow.location?.protocol === "https:" ? "; Secure" : "";
|
|
1107
|
+
browserWindow.document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${secure}; SameSite=Lax`;
|
|
1108
|
+
return true;
|
|
1109
|
+
} catch {
|
|
1110
|
+
return false;
|
|
470
1111
|
}
|
|
471
|
-
|
|
1112
|
+
}
|
|
1113
|
+
function removeCookie(name) {
|
|
1114
|
+
const browserWindow = getBrowserWindow();
|
|
1115
|
+
if (!browserWindow?.document) return;
|
|
1116
|
+
browserWindow.document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
1117
|
+
}
|
|
1118
|
+
function getLocalStorage() {
|
|
1119
|
+
const browserWindow = getBrowserWindow();
|
|
1120
|
+
try {
|
|
1121
|
+
return browserWindow?.localStorage;
|
|
1122
|
+
} catch {
|
|
1123
|
+
return void 0;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function getSessionStorage() {
|
|
1127
|
+
const browserWindow = getBrowserWindow();
|
|
1128
|
+
try {
|
|
1129
|
+
return browserWindow?.sessionStorage;
|
|
1130
|
+
} catch {
|
|
1131
|
+
return void 0;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
function createBrowserPersistence(mode = "localStorage+cookie") {
|
|
1135
|
+
const health = createPersistenceHealth(mode);
|
|
1136
|
+
const memory = createMemoryPersistence(health);
|
|
1137
|
+
if (mode === "none") {
|
|
1138
|
+
return {
|
|
1139
|
+
getItem() {
|
|
1140
|
+
return null;
|
|
1141
|
+
},
|
|
1142
|
+
setItem() {
|
|
1143
|
+
return false;
|
|
1144
|
+
},
|
|
1145
|
+
removeItem() {
|
|
1146
|
+
},
|
|
1147
|
+
getHealth() {
|
|
1148
|
+
return {
|
|
1149
|
+
...health,
|
|
1150
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
if (mode === "memory") return memory;
|
|
1156
|
+
const primary = mode === "sessionStorage" ? getSessionStorage() : getLocalStorage();
|
|
1157
|
+
const useCookie = mode === "cookie" || mode === "localStorage+cookie" || !primary;
|
|
1158
|
+
return {
|
|
1159
|
+
getItem(key) {
|
|
1160
|
+
try {
|
|
1161
|
+
const stored = primary?.getItem(key);
|
|
1162
|
+
if (stored) return stored;
|
|
1163
|
+
} catch (error) {
|
|
1164
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "get", error);
|
|
1165
|
+
}
|
|
1166
|
+
if (useCookie) {
|
|
1167
|
+
const cookie = getCookie2(key);
|
|
1168
|
+
if (cookie) {
|
|
1169
|
+
health.cookieFallbackUsed = true;
|
|
1170
|
+
return cookie;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
const value = memory.getItem(key);
|
|
1174
|
+
if (value !== null) health.memoryFallbackUsed = true;
|
|
1175
|
+
return value;
|
|
1176
|
+
},
|
|
1177
|
+
setItem(key, value) {
|
|
1178
|
+
let wrote = false;
|
|
1179
|
+
try {
|
|
1180
|
+
primary?.setItem(key, value);
|
|
1181
|
+
wrote = primary !== void 0;
|
|
1182
|
+
} catch (error) {
|
|
1183
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "set", error);
|
|
1184
|
+
wrote = false;
|
|
1185
|
+
}
|
|
1186
|
+
if (useCookie) {
|
|
1187
|
+
const cookieWrote = setCookie(key, value);
|
|
1188
|
+
if (cookieWrote) health.cookieFallbackUsed = true;
|
|
1189
|
+
wrote = cookieWrote || wrote;
|
|
1190
|
+
}
|
|
1191
|
+
if (!wrote) {
|
|
1192
|
+
health.memoryFallbackUsed = true;
|
|
1193
|
+
return memory.setItem(key, value);
|
|
1194
|
+
}
|
|
1195
|
+
if (mode === "localStorage+cookie") {
|
|
1196
|
+
memory.setItem(key, value);
|
|
1197
|
+
}
|
|
1198
|
+
return true;
|
|
1199
|
+
},
|
|
1200
|
+
removeItem(key) {
|
|
1201
|
+
try {
|
|
1202
|
+
primary?.removeItem(key);
|
|
1203
|
+
} catch (error) {
|
|
1204
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "remove", error);
|
|
1205
|
+
}
|
|
1206
|
+
if (useCookie) removeCookie(key);
|
|
1207
|
+
memory.removeItem(key);
|
|
1208
|
+
},
|
|
1209
|
+
getHealth() {
|
|
1210
|
+
return {
|
|
1211
|
+
...health,
|
|
1212
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
};
|
|
472
1216
|
}
|
|
473
1217
|
|
|
474
|
-
// src/browser/core/
|
|
475
|
-
|
|
476
|
-
|
|
1218
|
+
// src/browser/core/session.ts
|
|
1219
|
+
var SESSION_STORAGE_KEY2 = "sessionData";
|
|
1220
|
+
function getUrlParam2(name) {
|
|
1221
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1222
|
+
if (!href) return null;
|
|
1223
|
+
try {
|
|
1224
|
+
return new URL(href).searchParams.get(name);
|
|
1225
|
+
} catch {
|
|
1226
|
+
return null;
|
|
1227
|
+
}
|
|
477
1228
|
}
|
|
1229
|
+
function readStoredSession(persistence) {
|
|
1230
|
+
const rawSession = persistence.getItem(SESSION_STORAGE_KEY2);
|
|
1231
|
+
if (!rawSession) return void 0;
|
|
1232
|
+
try {
|
|
1233
|
+
const parsed = JSON.parse(rawSession);
|
|
1234
|
+
if (isUuid(parsed.sessionId) && typeof parsed.timestamp === "number") {
|
|
1235
|
+
return {
|
|
1236
|
+
sessionId: parsed.sessionId,
|
|
1237
|
+
timestamp: parsed.timestamp
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
} catch {
|
|
1241
|
+
persistence.removeItem(SESSION_STORAGE_KEY2);
|
|
1242
|
+
}
|
|
1243
|
+
return void 0;
|
|
1244
|
+
}
|
|
1245
|
+
function writeStoredSession(persistence, sessionId, timestamp) {
|
|
1246
|
+
persistence.setItem(SESSION_STORAGE_KEY2, JSON.stringify({ sessionId, timestamp }));
|
|
1247
|
+
}
|
|
1248
|
+
function createSessionManager(persistence, idleTimeoutSeconds = 30 * 60) {
|
|
1249
|
+
function resolveSessionId() {
|
|
1250
|
+
const now = Date.now();
|
|
1251
|
+
const urlSessionId = getUrlParam2("sid") ?? getUrlParam2("session_id");
|
|
1252
|
+
if (isUuid(urlSessionId)) {
|
|
1253
|
+
writeStoredSession(persistence, urlSessionId, now);
|
|
1254
|
+
return urlSessionId;
|
|
1255
|
+
}
|
|
1256
|
+
const storedSession = readStoredSession(persistence);
|
|
1257
|
+
if (storedSession && now - storedSession.timestamp <= idleTimeoutSeconds * 1e3) {
|
|
1258
|
+
writeStoredSession(persistence, storedSession.sessionId, now);
|
|
1259
|
+
return storedSession.sessionId;
|
|
1260
|
+
}
|
|
1261
|
+
const sessionId = createUuid();
|
|
1262
|
+
writeStoredSession(persistence, sessionId, now);
|
|
1263
|
+
return sessionId;
|
|
1264
|
+
}
|
|
1265
|
+
return {
|
|
1266
|
+
getSessionId() {
|
|
1267
|
+
return resolveSessionId();
|
|
1268
|
+
},
|
|
1269
|
+
reset() {
|
|
1270
|
+
const sessionId = createUuid();
|
|
1271
|
+
writeStoredSession(persistence, sessionId, Date.now());
|
|
1272
|
+
return sessionId;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/browser/core/DriveMetaDataSDK.ts
|
|
478
1278
|
function endpointFromConfig(config) {
|
|
479
1279
|
const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
|
|
480
1280
|
return `${host.replace(/\/$/, "")}/data-collector`;
|
|
@@ -485,14 +1285,6 @@ function requireConfigString(value, field) {
|
|
|
485
1285
|
}
|
|
486
1286
|
return value;
|
|
487
1287
|
}
|
|
488
|
-
function getBrowserStorage() {
|
|
489
|
-
const browserWindow = getBrowserWindow();
|
|
490
|
-
try {
|
|
491
|
-
return browserWindow?.localStorage;
|
|
492
|
-
} catch {
|
|
493
|
-
return void 0;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
1288
|
var DriveMetaDataSDK = class {
|
|
497
1289
|
constructor(config) {
|
|
498
1290
|
this.initialized = true;
|
|
@@ -505,30 +1297,36 @@ var DriveMetaDataSDK = class {
|
|
|
505
1297
|
requireConfigString(config.writeKey || config.token, "writeKey or token");
|
|
506
1298
|
this.config = config;
|
|
507
1299
|
this.endpoint = endpointFromConfig(config);
|
|
508
|
-
const
|
|
1300
|
+
const storagePersistence = createBrowserPersistence(config.persistence);
|
|
1301
|
+
this.persistence = createDmdAttributesPersistence(storagePersistence);
|
|
1302
|
+
this.session = createSessionManager(this.persistence, config.sessionIdleTimeoutSeconds);
|
|
509
1303
|
const deliveryConfig = {
|
|
510
|
-
endpoint: this.endpoint
|
|
1304
|
+
endpoint: this.endpoint,
|
|
1305
|
+
storage: storagePersistence
|
|
511
1306
|
};
|
|
512
1307
|
if (config.delivery?.maxQueueSize !== void 0) deliveryConfig.maxQueueSize = config.delivery.maxQueueSize;
|
|
513
1308
|
if (config.delivery?.queueTtlMs !== void 0) deliveryConfig.queueTtlMs = config.delivery.queueTtlMs;
|
|
514
1309
|
if (config.delivery?.retryDelayMs !== void 0) deliveryConfig.retryDelayMs = config.delivery.retryDelayMs;
|
|
515
1310
|
if (config.delivery?.maxRetryDelayMs !== void 0) deliveryConfig.maxRetryDelayMs = config.delivery.maxRetryDelayMs;
|
|
516
1311
|
if (config.delivery?.maxPayloadBytes !== void 0) deliveryConfig.maxPayloadBytes = config.delivery.maxPayloadBytes;
|
|
1312
|
+
if (config.delivery?.payloadSizePolicy !== void 0) deliveryConfig.payloadSizePolicy = config.delivery.payloadSizePolicy;
|
|
1313
|
+
if (config.delivery?.payloadTruncateStringLength !== void 0) {
|
|
1314
|
+
deliveryConfig.payloadTruncateStringLength = config.delivery.payloadTruncateStringLength;
|
|
1315
|
+
}
|
|
1316
|
+
if (config.delivery?.useBeacon !== void 0) deliveryConfig.useBeacon = config.delivery.useBeacon;
|
|
517
1317
|
if (config.delivery?.batchSize !== void 0) deliveryConfig.batchSize = config.delivery.batchSize;
|
|
518
1318
|
if (config.onDrop !== void 0) deliveryConfig.onDrop = config.onDrop;
|
|
519
1319
|
if (config.onError !== void 0) deliveryConfig.onError = config.onError;
|
|
520
|
-
this.delivery = createDeliveryManager(
|
|
521
|
-
...deliveryConfig,
|
|
522
|
-
storage
|
|
523
|
-
} : deliveryConfig);
|
|
1320
|
+
this.delivery = createDeliveryManager(deliveryConfig);
|
|
524
1321
|
this.initialRetryDelayMs = config.delivery?.retryDelayMs ?? 1e3;
|
|
525
1322
|
this.retryDelayMs = this.initialRetryDelayMs;
|
|
526
1323
|
this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
|
|
527
1324
|
this.writeKey = config.writeKey || config.token || "";
|
|
528
|
-
this.identity = { anonymousId:
|
|
529
|
-
this.
|
|
1325
|
+
this.identity = { anonymousId: resolveAnonymousId(this.persistence) };
|
|
1326
|
+
captureAttributionFromUrl(this.persistence);
|
|
530
1327
|
this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
|
|
531
1328
|
this.gdprConsent = this.consentState.analytics;
|
|
1329
|
+
this.installAutocapture();
|
|
532
1330
|
if (!config.delivery?.disableLifecycleFlush) {
|
|
533
1331
|
this.installLifecycleFlush();
|
|
534
1332
|
}
|
|
@@ -568,7 +1366,8 @@ var DriveMetaDataSDK = class {
|
|
|
568
1366
|
}
|
|
569
1367
|
}
|
|
570
1368
|
reset() {
|
|
571
|
-
this.identity = { anonymousId:
|
|
1369
|
+
this.identity = { anonymousId: resetAnonymousId(this.persistence) };
|
|
1370
|
+
this.session.reset();
|
|
572
1371
|
this.queue = [];
|
|
573
1372
|
this.offline = false;
|
|
574
1373
|
if (this.retryTimer !== void 0) {
|
|
@@ -577,8 +1376,20 @@ var DriveMetaDataSDK = class {
|
|
|
577
1376
|
}
|
|
578
1377
|
this.lifecycleCleanup?.();
|
|
579
1378
|
this.lifecycleCleanup = void 0;
|
|
1379
|
+
this.autocaptureCleanup?.();
|
|
1380
|
+
this.autocaptureCleanup = void 0;
|
|
580
1381
|
this.delivery.clearQueue("manual_clear");
|
|
581
1382
|
}
|
|
1383
|
+
disposeForTests() {
|
|
1384
|
+
if (this.retryTimer !== void 0) {
|
|
1385
|
+
clearTimeout(this.retryTimer);
|
|
1386
|
+
this.retryTimer = void 0;
|
|
1387
|
+
}
|
|
1388
|
+
this.lifecycleCleanup?.();
|
|
1389
|
+
this.lifecycleCleanup = void 0;
|
|
1390
|
+
this.autocaptureCleanup?.();
|
|
1391
|
+
this.autocaptureCleanup = void 0;
|
|
1392
|
+
}
|
|
582
1393
|
setConsent(consent2) {
|
|
583
1394
|
this.consentState = typeof consent2 === "object" ? mergeConsent(this.consentState, consent2) : normalizeConsent(consent2);
|
|
584
1395
|
this.gdprConsent = this.consentState.analytics;
|
|
@@ -593,6 +1404,7 @@ var DriveMetaDataSDK = class {
|
|
|
593
1404
|
initialized: this.initialized,
|
|
594
1405
|
consent: this.gdprConsent,
|
|
595
1406
|
consentPurposes: this.consentState,
|
|
1407
|
+
persistence: this.persistence.getHealth(),
|
|
596
1408
|
queueSize: deliveryDiagnostics.queued,
|
|
597
1409
|
offline: this.offline || deliveryDiagnostics.queued > 0,
|
|
598
1410
|
droppedEvents: this.droppedEvents + deliveryDiagnostics.dropped.length,
|
|
@@ -607,7 +1419,9 @@ var DriveMetaDataSDK = class {
|
|
|
607
1419
|
void this.delivery.send(payload).then(() => {
|
|
608
1420
|
const diagnostics = this.delivery.getDiagnostics();
|
|
609
1421
|
this.offline = diagnostics.queued > 0;
|
|
610
|
-
|
|
1422
|
+
if (diagnostics.lastError !== void 0) {
|
|
1423
|
+
this.lastError = diagnostics.lastError;
|
|
1424
|
+
}
|
|
611
1425
|
if (diagnostics.queued > 0) {
|
|
612
1426
|
this.scheduleRetryFlush();
|
|
613
1427
|
}
|
|
@@ -639,6 +1453,28 @@ var DriveMetaDataSDK = class {
|
|
|
639
1453
|
}
|
|
640
1454
|
};
|
|
641
1455
|
}
|
|
1456
|
+
installAutocapture() {
|
|
1457
|
+
const browserWindow = getBrowserWindow();
|
|
1458
|
+
if (!browserWindow) return;
|
|
1459
|
+
if (this.config.autocapture === false) return;
|
|
1460
|
+
const capturePageview = this.config.capturePageview !== false;
|
|
1461
|
+
const capturePageleave = this.config.capturePageleave !== false;
|
|
1462
|
+
const controller = installAutocapture({
|
|
1463
|
+
browserWindow,
|
|
1464
|
+
capturePageview,
|
|
1465
|
+
capturePageleave,
|
|
1466
|
+
onPageView: () => {
|
|
1467
|
+
this.page();
|
|
1468
|
+
},
|
|
1469
|
+
onPageLeave: () => {
|
|
1470
|
+
this.trackEvent("page_leave", { url: browserWindow.location.href });
|
|
1471
|
+
},
|
|
1472
|
+
onRouteChange: () => {
|
|
1473
|
+
captureAttributionFromUrl(this.persistence);
|
|
1474
|
+
}
|
|
1475
|
+
});
|
|
1476
|
+
this.autocaptureCleanup = controller.cleanup;
|
|
1477
|
+
}
|
|
642
1478
|
scheduleRetryFlush() {
|
|
643
1479
|
if (this.retryTimer !== void 0) return;
|
|
644
1480
|
const delay = Math.min(this.retryDelayMs, this.maxRetryDelayMs);
|
|
@@ -664,7 +1500,7 @@ var DriveMetaDataSDK = class {
|
|
|
664
1500
|
type,
|
|
665
1501
|
event,
|
|
666
1502
|
properties: sanitizeProperties(properties),
|
|
667
|
-
messageId: options.messageId
|
|
1503
|
+
messageId: ensureUuid(options.messageId),
|
|
668
1504
|
timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
669
1505
|
context: options.context ?? {},
|
|
670
1506
|
anonymousId: this.identity.anonymousId,
|
|
@@ -673,7 +1509,7 @@ var DriveMetaDataSDK = class {
|
|
|
673
1509
|
appId: this.config.appId,
|
|
674
1510
|
writeKey: this.writeKey,
|
|
675
1511
|
consent: this.consentState,
|
|
676
|
-
sessionId: this.
|
|
1512
|
+
sessionId: this.session.getSessionId()
|
|
677
1513
|
};
|
|
678
1514
|
if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
|
|
679
1515
|
if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
|
|
@@ -697,10 +1533,21 @@ var DriveMetaDataSDK = class {
|
|
|
697
1533
|
if (!validation.ok) {
|
|
698
1534
|
this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
|
|
699
1535
|
}
|
|
700
|
-
this.
|
|
1536
|
+
const collectorPayload = this.toCollectorPayload(prepared);
|
|
1537
|
+
const backendValidation = validateBackendCollectorPayload(collectorPayload);
|
|
1538
|
+
if (!backendValidation.ok && this.config.schemaValidation === "strict") {
|
|
1539
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1540
|
+
this.recordDrop(type, "invalid_payload", event);
|
|
1541
|
+
return;
|
|
1542
|
+
}
|
|
1543
|
+
if (!backendValidation.ok) {
|
|
1544
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1545
|
+
}
|
|
1546
|
+
this.sendEvent(collectorPayload);
|
|
701
1547
|
}
|
|
702
1548
|
toCollectorPayload(prepared) {
|
|
703
1549
|
const browserWindow = getBrowserWindow();
|
|
1550
|
+
const pageContext = getBrowserPageContext();
|
|
704
1551
|
return createBackendCollectorPayload({
|
|
705
1552
|
requestId: prepared.messageId,
|
|
706
1553
|
timestamp: prepared.timestamp,
|
|
@@ -712,15 +1559,19 @@ var DriveMetaDataSDK = class {
|
|
|
712
1559
|
sessionId: prepared.sessionId,
|
|
713
1560
|
ua: browserWindow?.navigator?.userAgent,
|
|
714
1561
|
appId: prepared.appId,
|
|
715
|
-
pageUrl: browserWindow?.location?.href,
|
|
716
|
-
eventData: {
|
|
1562
|
+
pageUrl: pageContext.url ?? browserWindow?.location?.href,
|
|
1563
|
+
eventData: mergeStoredAttribution({
|
|
717
1564
|
...prepared.properties,
|
|
1565
|
+
page: {
|
|
1566
|
+
...pageContext,
|
|
1567
|
+
...prepared.properties.page && typeof prepared.properties.page === "object" ? prepared.properties.page : {}
|
|
1568
|
+
},
|
|
718
1569
|
anonymousId: prepared.anonymousId,
|
|
719
1570
|
sessionId: prepared.sessionId,
|
|
720
1571
|
timestamp: prepared.timestamp,
|
|
721
1572
|
requestSentAt: prepared.timestamp,
|
|
722
1573
|
requestReceivedAt: prepared.timestamp
|
|
723
|
-
}
|
|
1574
|
+
}, this.persistence)
|
|
724
1575
|
});
|
|
725
1576
|
}
|
|
726
1577
|
recordDrop(type, reason, event) {
|
|
@@ -796,7 +1647,7 @@ function initDmdSDK(config) {
|
|
|
796
1647
|
return publicSingleton;
|
|
797
1648
|
}
|
|
798
1649
|
try {
|
|
799
|
-
const instance = new DriveMetaDataSDK(config);
|
|
1650
|
+
const instance = new DriveMetaDataSDK(normalizeBrowserConfig(config));
|
|
800
1651
|
return setSingleton(instance);
|
|
801
1652
|
} catch (error) {
|
|
802
1653
|
lastError = error instanceof Error ? error.message : String(error);
|
|
@@ -890,7 +1741,7 @@ function getDmdHealth() {
|
|
|
890
1741
|
return health;
|
|
891
1742
|
}
|
|
892
1743
|
function resetDmdSDKForTests() {
|
|
893
|
-
singleton?.
|
|
1744
|
+
singleton?.disposeForTests();
|
|
894
1745
|
singleton = void 0;
|
|
895
1746
|
publicSingleton = void 0;
|
|
896
1747
|
droppedEvents = 0;
|