@drivemetadata-ai/sdk 0.1.1-beta.1 → 0.1.1-beta.4
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 +18 -15
- package/dist/angular/index.cjs +880 -191
- 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 +880 -191
- package/dist/angular/index.js.map +1 -1
- package/dist/browser/index.cjs +881 -192
- package/dist/browser/index.cjs.map +1 -1
- package/dist/browser/index.d.cts +5 -68
- package/dist/browser/index.d.ts +5 -68
- package/dist/browser/index.js +881 -192
- package/dist/browser/index.js.map +1 -1
- package/dist/next/index.cjs +881 -191
- 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 +881 -191
- package/dist/next/index.js.map +1 -1
- package/dist/node/index.cjs +152 -7
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.d.cts +7 -1
- package/dist/node/index.d.ts +7 -1
- package/dist/node/index.js +152 -7
- package/dist/node/index.js.map +1 -1
- package/dist/react/index.cjs +881 -191
- 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 +881 -191
- package/dist/react/index.js.map +1 -1
- package/dist/{types-BwtS0ZDu.d.cts → types-mgbdL1V7.d.cts} +24 -7
- package/dist/{types-BwtS0ZDu.d.ts → types-mgbdL1V7.d.ts} +24 -7
- package/docs/angular-integration.md +6 -6
- package/docs/architecture.md +109 -0
- package/docs/index.md +5 -6
- package/docs/integration.md +348 -0
- package/docs/node-server-integration.md +16 -7
- package/docs/npm-browser-sdk.md +6 -6
- package/docs/react-next-integration.md +9 -9
- package/docs/security-privacy.md +11 -11
- package/package.json +6 -6
- package/docs/migration-cdn-to-npm.md +0 -99
package/dist/browser/index.js
CHANGED
|
@@ -1,55 +1,151 @@
|
|
|
1
|
-
// src/core/config.ts
|
|
2
|
-
function
|
|
3
|
-
if (
|
|
4
|
-
|
|
1
|
+
// src/browser/core/browser-config.ts
|
|
2
|
+
function setIfDefined(target, key, value) {
|
|
3
|
+
if (value !== void 0) {
|
|
4
|
+
target[key] = value;
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
function normalizeBrowserConfig(input) {
|
|
8
|
+
const normalized = {
|
|
9
|
+
...input,
|
|
10
|
+
clientId: input.clientId ?? "",
|
|
11
|
+
workspaceId: input.workspaceId ?? "",
|
|
12
|
+
appId: input.appId ?? ""
|
|
13
|
+
};
|
|
14
|
+
setIfDefined(normalized, "apiHost", input.apiHost);
|
|
15
|
+
setIfDefined(normalized, "capturePageview", input.capturePageview);
|
|
16
|
+
setIfDefined(normalized, "capturePageleave", input.capturePageleave);
|
|
17
|
+
setIfDefined(normalized, "captureDeadClicks", input.captureDeadClicks);
|
|
18
|
+
setIfDefined(normalized, "crossSubdomainCookie", input.crossSubdomainCookie);
|
|
19
|
+
setIfDefined(normalized, "sessionIdleTimeoutSeconds", input.sessionIdleTimeoutSeconds);
|
|
20
|
+
setIfDefined(normalized, "schemaValidation", input.schemaValidation);
|
|
21
|
+
setIfDefined(normalized, "beforeSend", input.beforeSend);
|
|
22
|
+
setIfDefined(normalized, "persistence", input.disablePersistence === true ? "none" : input.persistence);
|
|
23
|
+
return normalized;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// src/core/uuid.ts
|
|
27
|
+
function createUuid() {
|
|
28
|
+
const cryptoApi = globalThis.crypto;
|
|
29
|
+
if (typeof cryptoApi?.randomUUID === "function") {
|
|
30
|
+
return cryptoApi.randomUUID();
|
|
31
|
+
}
|
|
32
|
+
const bytes = new Uint8Array(16);
|
|
33
|
+
if (typeof cryptoApi?.getRandomValues === "function") {
|
|
34
|
+
cryptoApi.getRandomValues(bytes);
|
|
35
|
+
} else {
|
|
36
|
+
for (let index = 0; index < bytes.length; index += 1) {
|
|
37
|
+
bytes[index] = Math.floor(Math.random() * 256);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
bytes[6] = (bytes[6] ?? 0) & 15 | 64;
|
|
41
|
+
bytes[8] = (bytes[8] ?? 0) & 63 | 128;
|
|
42
|
+
const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
43
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
44
|
+
}
|
|
45
|
+
function isUuid(value) {
|
|
46
|
+
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);
|
|
47
|
+
}
|
|
48
|
+
function ensureUuid(value) {
|
|
49
|
+
return isUuid(value) ? value : createUuid();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/core/backend-payload.ts
|
|
53
|
+
function formatUtcTimestamp(value) {
|
|
54
|
+
const date = typeof value === "string" || typeof value === "number" || value instanceof Date ? new Date(value) : /* @__PURE__ */ new Date();
|
|
55
|
+
const safeDate = Number.isNaN(date.getTime()) ? /* @__PURE__ */ new Date() : date;
|
|
56
|
+
return safeDate.toISOString().replace("T", " ").slice(0, 19);
|
|
57
|
+
}
|
|
58
|
+
function cleanObject(value) {
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
const cleaned = value.map((item) => cleanObject(item)).filter((item) => item !== null && item !== void 0 && item !== "");
|
|
61
|
+
return cleaned.length > 0 ? cleaned : void 0;
|
|
62
|
+
}
|
|
63
|
+
if (value && typeof value === "object") {
|
|
64
|
+
const cleaned = Object.fromEntries(
|
|
65
|
+
Object.entries(value).map(([key, item]) => [key, cleanObject(item)]).filter(([, item]) => {
|
|
66
|
+
if (item === null || item === void 0 || item === "") return false;
|
|
67
|
+
if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 0) return false;
|
|
68
|
+
return true;
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
5
72
|
}
|
|
6
73
|
return value;
|
|
7
74
|
}
|
|
8
|
-
function
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
75
|
+
function createBackendCollectorPayload(input) {
|
|
76
|
+
const eventData = input.eventData && typeof input.eventData === "object" ? input.eventData : {};
|
|
77
|
+
const page2 = eventData.page && typeof eventData.page === "object" ? eventData.page : {};
|
|
78
|
+
const timestamp = formatUtcTimestamp(eventData.timestamp ?? input.timestamp);
|
|
79
|
+
const normalizedEventData = {
|
|
80
|
+
...eventData,
|
|
81
|
+
timestamp,
|
|
82
|
+
requestSentAt: formatUtcTimestamp(eventData.requestSentAt ?? input.requestSentAt ?? timestamp),
|
|
83
|
+
requestReceivedAt: formatUtcTimestamp(eventData.requestReceivedAt ?? input.requestReceivedAt ?? timestamp)
|
|
15
84
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
if (config.beforeSend !== void 0) legacyConfig.before_send = config.beforeSend;
|
|
41
|
-
return legacyConfig;
|
|
85
|
+
const metaData = {
|
|
86
|
+
...normalizedEventData,
|
|
87
|
+
requestId: ensureUuid(typeof input.requestId === "string" ? input.requestId : void 0),
|
|
88
|
+
timestamp,
|
|
89
|
+
eventType: input.eventType,
|
|
90
|
+
requestFrom: input.requestFrom ?? "3",
|
|
91
|
+
clientId: input.clientId,
|
|
92
|
+
workspaceId: input.workspaceId,
|
|
93
|
+
token: input.token,
|
|
94
|
+
anonymousId: ensureUuid(
|
|
95
|
+
typeof eventData.anonymousId === "string" ? eventData.anonymousId : typeof input.anonymousId === "string" ? input.anonymousId : void 0
|
|
96
|
+
),
|
|
97
|
+
sessionId: ensureUuid(
|
|
98
|
+
typeof eventData.sessionId === "string" ? eventData.sessionId : typeof input.sessionId === "string" ? input.sessionId : void 0
|
|
99
|
+
),
|
|
100
|
+
ua: input.ua,
|
|
101
|
+
appDetails: { app_id: input.appId },
|
|
102
|
+
page: { ...page2, url: page2.url ?? input.pageUrl },
|
|
103
|
+
requestSentAt: normalizedEventData.requestSentAt,
|
|
104
|
+
requestReceivedAt: normalizedEventData.requestReceivedAt
|
|
105
|
+
};
|
|
106
|
+
const payload = { metaData };
|
|
107
|
+
return cleanObject(payload);
|
|
42
108
|
}
|
|
43
109
|
|
|
44
|
-
// src/core/
|
|
45
|
-
|
|
46
|
-
|
|
110
|
+
// src/core/backend-schema.ts
|
|
111
|
+
var requiredMetaDataFields = [
|
|
112
|
+
"requestId",
|
|
113
|
+
"timestamp",
|
|
114
|
+
"eventType",
|
|
115
|
+
"requestFrom",
|
|
116
|
+
"clientId",
|
|
117
|
+
"workspaceId",
|
|
118
|
+
"anonymousId",
|
|
119
|
+
"sessionId"
|
|
120
|
+
];
|
|
121
|
+
function isPresent(value) {
|
|
122
|
+
return value !== null && value !== void 0 && value !== "";
|
|
47
123
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
124
|
+
function validateBackendCollectorPayload(payload) {
|
|
125
|
+
const errors = [];
|
|
126
|
+
const metaData = payload.metaData;
|
|
127
|
+
if (!metaData || typeof metaData !== "object" || Array.isArray(metaData)) {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
errors: ["metaData is required"]
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const metadataRecord = metaData;
|
|
134
|
+
for (const field of requiredMetaDataFields) {
|
|
135
|
+
if (!isPresent(metadataRecord[field])) {
|
|
136
|
+
errors.push(`metaData.${field} is required`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (isPresent(metadataRecord.eventType) && typeof metadataRecord.eventType !== "string") {
|
|
140
|
+
errors.push("metaData.eventType must be a string");
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
ok: errors.length === 0,
|
|
144
|
+
errors
|
|
145
|
+
};
|
|
50
146
|
}
|
|
51
147
|
|
|
52
|
-
// src/
|
|
148
|
+
// src/core/consent.ts
|
|
53
149
|
var purposes = [
|
|
54
150
|
"analytics",
|
|
55
151
|
"advertising",
|
|
@@ -89,6 +185,335 @@ function canCollectPurpose(consent2, purpose) {
|
|
|
89
185
|
return consent2[purpose] === "granted";
|
|
90
186
|
}
|
|
91
187
|
|
|
188
|
+
// src/core/event-schema.ts
|
|
189
|
+
var reservedKeys = /* @__PURE__ */ new Set(["messageId", "timestamp", "type", "event", "anonymousId", "userId", "context"]);
|
|
190
|
+
function validateEventEnvelope(envelope, options = {}) {
|
|
191
|
+
if (options.mode === "off") return { ok: true, errors: [] };
|
|
192
|
+
const errors = [];
|
|
193
|
+
if (typeof envelope.type !== "string") errors.push("type must be a string");
|
|
194
|
+
if (envelope.type === "track" && typeof envelope.event !== "string") {
|
|
195
|
+
errors.push("track event must include event name");
|
|
196
|
+
}
|
|
197
|
+
if (typeof envelope.messageId !== "string") errors.push("messageId must be a string");
|
|
198
|
+
if (typeof envelope.timestamp !== "string") errors.push("timestamp must be an ISO string");
|
|
199
|
+
for (const key of Object.keys(envelope.properties ?? {})) {
|
|
200
|
+
if (reservedKeys.has(key)) errors.push(`properties.${key} is reserved`);
|
|
201
|
+
}
|
|
202
|
+
return { ok: errors.length === 0, errors };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/core/environment.ts
|
|
206
|
+
function getBrowserWindow() {
|
|
207
|
+
return typeof window === "undefined" ? void 0 : window;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// src/core/privacy.ts
|
|
211
|
+
var sensitiveKeys = /* @__PURE__ */ new Set([
|
|
212
|
+
"email",
|
|
213
|
+
"phone",
|
|
214
|
+
"mobile",
|
|
215
|
+
"address",
|
|
216
|
+
"address1",
|
|
217
|
+
"address2",
|
|
218
|
+
"first_name",
|
|
219
|
+
"last_name",
|
|
220
|
+
"name",
|
|
221
|
+
"token",
|
|
222
|
+
"secret",
|
|
223
|
+
"password",
|
|
224
|
+
"session",
|
|
225
|
+
"cookie"
|
|
226
|
+
]);
|
|
227
|
+
function sanitizeValue(value, allow, path = []) {
|
|
228
|
+
if (Array.isArray(value)) {
|
|
229
|
+
return value.map((item) => sanitizeValue(item, allow, path));
|
|
230
|
+
}
|
|
231
|
+
if (value && typeof value === "object") {
|
|
232
|
+
return Object.fromEntries(
|
|
233
|
+
Object.entries(value).filter(([key]) => {
|
|
234
|
+
const lowerKey = key.toLowerCase();
|
|
235
|
+
const lowerPath = path.map((item) => item.toLowerCase());
|
|
236
|
+
const isEcommerceItemName = lowerKey === "name" && lowerPath.includes("ecommerce") && lowerPath.includes("items");
|
|
237
|
+
return isEcommerceItemName || !sensitiveKeys.has(lowerKey) || allow.has(lowerKey);
|
|
238
|
+
}).map(([key, nestedValue]) => [key, sanitizeValue(nestedValue, allow, [...path, key])])
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
function sanitizeProperties(input, allowRawKeys = []) {
|
|
244
|
+
const allow = new Set(allowRawKeys.map((key) => key.toLowerCase()));
|
|
245
|
+
return sanitizeValue(input, allow);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// src/core/attribution.ts
|
|
249
|
+
var dmdUtmKeys = [
|
|
250
|
+
"utm_source",
|
|
251
|
+
"utm_medium",
|
|
252
|
+
"utm_campaign",
|
|
253
|
+
"utm_term",
|
|
254
|
+
"utm_content",
|
|
255
|
+
"utm_id"
|
|
256
|
+
];
|
|
257
|
+
var dmdCampaignKeys = ["campaign_id", "ad_id"];
|
|
258
|
+
var dmdClickIdSources = [
|
|
259
|
+
["gclid", 2],
|
|
260
|
+
["fbclid", 3],
|
|
261
|
+
["ScCid", 1],
|
|
262
|
+
["li_fat_id", 4]
|
|
263
|
+
];
|
|
264
|
+
function cleanAttributionRecord(record) {
|
|
265
|
+
const cleaned = Object.fromEntries(
|
|
266
|
+
Object.entries(record).filter(([, value]) => value !== null && value !== void 0 && value !== "")
|
|
267
|
+
);
|
|
268
|
+
return Object.keys(cleaned).length > 0 ? cleaned : void 0;
|
|
269
|
+
}
|
|
270
|
+
function objectValue(value) {
|
|
271
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
272
|
+
}
|
|
273
|
+
function mergeAttributionRecords(explicitProperties, stored) {
|
|
274
|
+
const attributionData = objectValue(explicitProperties.attributionData);
|
|
275
|
+
const utmParameter = objectValue(explicitProperties.utmParameter);
|
|
276
|
+
return {
|
|
277
|
+
...explicitProperties,
|
|
278
|
+
...stored.attributionData || attributionData ? { attributionData: { ...stored.attributionData ?? {}, ...attributionData ?? {} } } : {},
|
|
279
|
+
...stored.utmParameter || utmParameter ? { utmParameter: { ...stored.utmParameter ?? {}, ...utmParameter ?? {} } } : {}
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/browser/core/attribution.ts
|
|
284
|
+
function getCurrentUrl() {
|
|
285
|
+
return getBrowserWindow()?.location?.href;
|
|
286
|
+
}
|
|
287
|
+
function getCookie(name) {
|
|
288
|
+
const cookie = getBrowserWindow()?.document?.cookie;
|
|
289
|
+
if (!cookie) return void 0;
|
|
290
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
291
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
292
|
+
return match ? decodeURIComponent(match[1] ?? "") : void 0;
|
|
293
|
+
}
|
|
294
|
+
function getParams(url) {
|
|
295
|
+
return new URL(url, "https://placeholder.local").searchParams;
|
|
296
|
+
}
|
|
297
|
+
function setIfPresent(persistence, key, value) {
|
|
298
|
+
if (value !== null && value !== "") {
|
|
299
|
+
persistence.setItem(key, value);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function getStoredString(persistence, key) {
|
|
303
|
+
const value = persistence.getItem(key);
|
|
304
|
+
return value === null || value === "" ? void 0 : value;
|
|
305
|
+
}
|
|
306
|
+
function getStoredNumberOrString(persistence, key) {
|
|
307
|
+
const value = getStoredString(persistence, key);
|
|
308
|
+
if (value === void 0) return void 0;
|
|
309
|
+
const parsed = Number.parseInt(value, 10);
|
|
310
|
+
return Number.isNaN(parsed) ? value : parsed;
|
|
311
|
+
}
|
|
312
|
+
function captureAttributionFromUrl(persistence, url = getCurrentUrl()) {
|
|
313
|
+
if (!url) return;
|
|
314
|
+
const params = getParams(url);
|
|
315
|
+
for (const key of dmdUtmKeys) {
|
|
316
|
+
setIfPresent(persistence, key, params.get(key));
|
|
317
|
+
}
|
|
318
|
+
for (const key of dmdCampaignKeys) {
|
|
319
|
+
setIfPresent(persistence, key, params.get(key));
|
|
320
|
+
}
|
|
321
|
+
for (const [param, sdkPubId] of dmdClickIdSources) {
|
|
322
|
+
const value = params.get(param);
|
|
323
|
+
if (value) {
|
|
324
|
+
persistence.setItem("unique_id", value);
|
|
325
|
+
persistence.setItem("sdk_pub_id", String(sdkPubId));
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
function getStoredAttributionData(persistence) {
|
|
330
|
+
return cleanAttributionRecord({
|
|
331
|
+
unique_id: getStoredString(persistence, "unique_id"),
|
|
332
|
+
sdk_pub_id: getStoredNumberOrString(persistence, "sdk_pub_id"),
|
|
333
|
+
fbc: getStoredString(persistence, "fbc") ?? getCookie("_fbc"),
|
|
334
|
+
fbp: getStoredString(persistence, "fbp") ?? getCookie("_fbp"),
|
|
335
|
+
campaign_id: getStoredString(persistence, "campaign_id"),
|
|
336
|
+
ad_id: getStoredString(persistence, "ad_id")
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
function getStoredUtmParameter(persistence) {
|
|
340
|
+
return cleanAttributionRecord(Object.fromEntries(dmdUtmKeys.map((key) => [key, getStoredString(persistence, key)])));
|
|
341
|
+
}
|
|
342
|
+
function mergeStoredAttribution(properties, persistence) {
|
|
343
|
+
const stored = {};
|
|
344
|
+
const attributionData = getStoredAttributionData(persistence);
|
|
345
|
+
const utmParameter = getStoredUtmParameter(persistence);
|
|
346
|
+
if (attributionData !== void 0) stored.attributionData = attributionData;
|
|
347
|
+
if (utmParameter !== void 0) stored.utmParameter = utmParameter;
|
|
348
|
+
return mergeAttributionRecords(properties, stored);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/browser/core/autocapture.ts
|
|
352
|
+
function installAutocapture(config) {
|
|
353
|
+
const trackedPageUrls = /* @__PURE__ */ new Set();
|
|
354
|
+
const timers = /* @__PURE__ */ new Set();
|
|
355
|
+
const pageviewDelayMs = config.pageviewDelayMs ?? 500;
|
|
356
|
+
const history = config.browserWindow.history;
|
|
357
|
+
const originalPushState = history?.pushState;
|
|
358
|
+
const originalReplaceState = history?.replaceState;
|
|
359
|
+
function clearTimer(timer) {
|
|
360
|
+
timers.delete(timer);
|
|
361
|
+
clearTimeout(timer);
|
|
362
|
+
}
|
|
363
|
+
function canonicalUrl() {
|
|
364
|
+
return config.browserWindow.location.href;
|
|
365
|
+
}
|
|
366
|
+
function trackCurrentPageview() {
|
|
367
|
+
if (!config.capturePageview) return;
|
|
368
|
+
const url = canonicalUrl();
|
|
369
|
+
if (trackedPageUrls.has(url)) return;
|
|
370
|
+
trackedPageUrls.add(url);
|
|
371
|
+
config.onPageView();
|
|
372
|
+
}
|
|
373
|
+
function schedulePageview(delayMs) {
|
|
374
|
+
if (!config.capturePageview) return;
|
|
375
|
+
const timer = setTimeout(() => {
|
|
376
|
+
timers.delete(timer);
|
|
377
|
+
trackCurrentPageview();
|
|
378
|
+
}, delayMs);
|
|
379
|
+
timers.add(timer);
|
|
380
|
+
}
|
|
381
|
+
function handleRouteChange() {
|
|
382
|
+
config.onRouteChange?.();
|
|
383
|
+
trackCurrentPageview();
|
|
384
|
+
}
|
|
385
|
+
function wrapHistoryMethod(method) {
|
|
386
|
+
if (!history) return;
|
|
387
|
+
const original = history[method];
|
|
388
|
+
if (typeof original !== "function") return;
|
|
389
|
+
history[method] = function wrappedHistoryMethod(...args) {
|
|
390
|
+
const result = original.apply(this, args);
|
|
391
|
+
const timer = setTimeout(() => {
|
|
392
|
+
timers.delete(timer);
|
|
393
|
+
handleRouteChange();
|
|
394
|
+
}, 0);
|
|
395
|
+
timers.add(timer);
|
|
396
|
+
return result;
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
function handlePopOrHashChange() {
|
|
400
|
+
handleRouteChange();
|
|
401
|
+
}
|
|
402
|
+
function handlePageLeave() {
|
|
403
|
+
if (config.capturePageleave) {
|
|
404
|
+
config.onPageLeave();
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
schedulePageview(pageviewDelayMs);
|
|
408
|
+
wrapHistoryMethod("pushState");
|
|
409
|
+
wrapHistoryMethod("replaceState");
|
|
410
|
+
const canListen = typeof config.browserWindow.addEventListener === "function" && typeof config.browserWindow.removeEventListener === "function";
|
|
411
|
+
if (canListen) {
|
|
412
|
+
config.browserWindow.addEventListener("popstate", handlePopOrHashChange);
|
|
413
|
+
config.browserWindow.addEventListener("hashchange", handlePopOrHashChange);
|
|
414
|
+
config.browserWindow.addEventListener("beforeunload", handlePageLeave);
|
|
415
|
+
}
|
|
416
|
+
return {
|
|
417
|
+
cleanup() {
|
|
418
|
+
for (const timer of Array.from(timers)) {
|
|
419
|
+
clearTimer(timer);
|
|
420
|
+
}
|
|
421
|
+
if (history && originalPushState) history.pushState = originalPushState;
|
|
422
|
+
if (history && originalReplaceState) history.replaceState = originalReplaceState;
|
|
423
|
+
if (canListen) {
|
|
424
|
+
config.browserWindow.removeEventListener("popstate", handlePopOrHashChange);
|
|
425
|
+
config.browserWindow.removeEventListener("hashchange", handlePopOrHashChange);
|
|
426
|
+
config.browserWindow.removeEventListener("beforeunload", handlePageLeave);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/core/payload-size.ts
|
|
433
|
+
var preserveStringKeys = /* @__PURE__ */ new Set([
|
|
434
|
+
"requestId",
|
|
435
|
+
"eventType",
|
|
436
|
+
"requestFrom",
|
|
437
|
+
"clientId",
|
|
438
|
+
"workspaceId",
|
|
439
|
+
"anonymousId",
|
|
440
|
+
"sessionId",
|
|
441
|
+
"token"
|
|
442
|
+
]);
|
|
443
|
+
function payloadByteLength(payload) {
|
|
444
|
+
const serialized = JSON.stringify(payload);
|
|
445
|
+
if (typeof TextEncoder !== "undefined") {
|
|
446
|
+
return new TextEncoder().encode(serialized).length;
|
|
447
|
+
}
|
|
448
|
+
return serialized.length;
|
|
449
|
+
}
|
|
450
|
+
function clonePayload(payload) {
|
|
451
|
+
try {
|
|
452
|
+
return JSON.parse(JSON.stringify(payload));
|
|
453
|
+
} catch {
|
|
454
|
+
return void 0;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
function truncateValue(value, truncateStringLength, key) {
|
|
458
|
+
if (typeof value === "string") {
|
|
459
|
+
if (key && preserveStringKeys.has(key)) return value;
|
|
460
|
+
if (value.length <= truncateStringLength) return value;
|
|
461
|
+
return `${value.slice(0, truncateStringLength)}...[TRUNCATED]`;
|
|
462
|
+
}
|
|
463
|
+
if (Array.isArray(value)) {
|
|
464
|
+
return value.map((item) => truncateValue(item, truncateStringLength));
|
|
465
|
+
}
|
|
466
|
+
if (value && typeof value === "object") {
|
|
467
|
+
return Object.fromEntries(
|
|
468
|
+
Object.entries(value).map(([childKey, childValue]) => [
|
|
469
|
+
childKey,
|
|
470
|
+
truncateValue(childValue, truncateStringLength, childKey)
|
|
471
|
+
])
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
return value;
|
|
475
|
+
}
|
|
476
|
+
function markPayloadTruncated(payload) {
|
|
477
|
+
if (payload.metaData && typeof payload.metaData === "object" && !Array.isArray(payload.metaData)) {
|
|
478
|
+
return {
|
|
479
|
+
...payload,
|
|
480
|
+
metaData: {
|
|
481
|
+
...payload.metaData,
|
|
482
|
+
payloadTruncated: true
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
return {
|
|
487
|
+
...payload,
|
|
488
|
+
payloadTruncated: true
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function truncatePayload(payload, truncateStringLength) {
|
|
492
|
+
const cloned = clonePayload(payload);
|
|
493
|
+
if (!cloned) return void 0;
|
|
494
|
+
return markPayloadTruncated(truncateValue(cloned, truncateStringLength));
|
|
495
|
+
}
|
|
496
|
+
function getPayloadMessageId(payload) {
|
|
497
|
+
const value = payload.metaData?.requestId ?? payload.messageId;
|
|
498
|
+
return value === void 0 ? void 0 : String(value);
|
|
499
|
+
}
|
|
500
|
+
function preparePayloadForSizePolicy(payload, options = {}) {
|
|
501
|
+
const maxPayloadBytes = options.maxPayloadBytes ?? 64e3;
|
|
502
|
+
const payloadSizePolicy = options.payloadSizePolicy ?? "drop";
|
|
503
|
+
const payloadTruncateStringLength = options.payloadTruncateStringLength ?? 1024;
|
|
504
|
+
if (payloadByteLength(payload) <= maxPayloadBytes) {
|
|
505
|
+
return { ok: true, payload, truncated: false };
|
|
506
|
+
}
|
|
507
|
+
if (payloadSizePolicy === "truncate") {
|
|
508
|
+
const truncatedPayload = truncatePayload(payload, payloadTruncateStringLength);
|
|
509
|
+
if (truncatedPayload && payloadByteLength(truncatedPayload) <= maxPayloadBytes) {
|
|
510
|
+
return { ok: true, payload: truncatedPayload, truncated: true };
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const messageId = getPayloadMessageId(payload);
|
|
514
|
+
return messageId === void 0 ? { ok: false, reason: "payload_too_large" } : { ok: false, reason: "payload_too_large", messageId };
|
|
515
|
+
}
|
|
516
|
+
|
|
92
517
|
// src/browser/core/delivery.ts
|
|
93
518
|
function createId(prefix) {
|
|
94
519
|
return `${prefix}_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
|
|
@@ -104,8 +529,9 @@ function stableStringify(value) {
|
|
|
104
529
|
);
|
|
105
530
|
}
|
|
106
531
|
function createIdempotencyKey(payload, messageId) {
|
|
107
|
-
const
|
|
108
|
-
const
|
|
532
|
+
const metaData = payload.metaData;
|
|
533
|
+
const event = String(metaData?.eventType ?? payload.event ?? payload.type ?? "event");
|
|
534
|
+
const properties = metaData ?? payload.properties;
|
|
109
535
|
const orderId = properties?.orderId ?? properties?.order_id ?? properties?.transaction_id;
|
|
110
536
|
if (orderId !== void 0) return `${event}:${String(orderId)}`;
|
|
111
537
|
return `${event}:${stableStringify(properties ?? {}) || messageId}`;
|
|
@@ -119,7 +545,6 @@ function createDeliveryManager(config) {
|
|
|
119
545
|
const lockTtlMs = config.lockTtlMs ?? 5e3;
|
|
120
546
|
const tabId = config.tabId ?? createId("tab");
|
|
121
547
|
const batchSize = config.batchSize ?? 25;
|
|
122
|
-
const maxPayloadBytes = config.maxPayloadBytes ?? 64e3;
|
|
123
548
|
function recordDrop(event) {
|
|
124
549
|
diagnostics.dropped.push(event);
|
|
125
550
|
config.onDrop?.(event);
|
|
@@ -128,12 +553,22 @@ function createDeliveryManager(config) {
|
|
|
128
553
|
diagnostics.lastError = error.message;
|
|
129
554
|
config.onError?.(error);
|
|
130
555
|
}
|
|
131
|
-
function
|
|
132
|
-
const
|
|
133
|
-
if (
|
|
134
|
-
|
|
556
|
+
function preparePayloadForSend(payload) {
|
|
557
|
+
const sizePolicyOptions = {};
|
|
558
|
+
if (config.maxPayloadBytes !== void 0) sizePolicyOptions.maxPayloadBytes = config.maxPayloadBytes;
|
|
559
|
+
if (config.payloadSizePolicy !== void 0) sizePolicyOptions.payloadSizePolicy = config.payloadSizePolicy;
|
|
560
|
+
if (config.payloadTruncateStringLength !== void 0) {
|
|
561
|
+
sizePolicyOptions.payloadTruncateStringLength = config.payloadTruncateStringLength;
|
|
135
562
|
}
|
|
136
|
-
|
|
563
|
+
const prepared = preparePayloadForSizePolicy(payload, sizePolicyOptions);
|
|
564
|
+
if (prepared.ok) return prepared.payload;
|
|
565
|
+
const diagnostic = {
|
|
566
|
+
reason: prepared.reason,
|
|
567
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
568
|
+
};
|
|
569
|
+
if (prepared.messageId !== void 0) diagnostic.messageId = prepared.messageId;
|
|
570
|
+
recordDrop(diagnostic);
|
|
571
|
+
return void 0;
|
|
137
572
|
}
|
|
138
573
|
function recordStorageUnavailable() {
|
|
139
574
|
recordDrop({
|
|
@@ -206,14 +641,36 @@ function createDeliveryManager(config) {
|
|
|
206
641
|
persistQueue();
|
|
207
642
|
}
|
|
208
643
|
function withEnvelope(payload) {
|
|
209
|
-
const
|
|
644
|
+
const metaData = payload.metaData;
|
|
645
|
+
const messageId = String(metaData?.requestId ?? payload.messageId ?? createId("msg"));
|
|
646
|
+
if (metaData) {
|
|
647
|
+
return {
|
|
648
|
+
...payload,
|
|
649
|
+
metaData: {
|
|
650
|
+
...metaData,
|
|
651
|
+
requestId: messageId
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
210
655
|
return {
|
|
211
656
|
...payload,
|
|
212
657
|
messageId,
|
|
213
658
|
idempotencyKey: String(payload.idempotencyKey ?? createIdempotencyKey(payload, messageId))
|
|
214
659
|
};
|
|
215
660
|
}
|
|
661
|
+
function tryBeacon(body) {
|
|
662
|
+
if (!config.useBeacon) return false;
|
|
663
|
+
const sendBeacon = globalThis.navigator?.sendBeacon;
|
|
664
|
+
if (typeof sendBeacon !== "function") return false;
|
|
665
|
+
try {
|
|
666
|
+
const blob = new Blob([JSON.stringify(body)], { type: "application/json" });
|
|
667
|
+
return sendBeacon.call(globalThis.navigator, config.endpoint, blob);
|
|
668
|
+
} catch {
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
216
672
|
async function deliver(body) {
|
|
673
|
+
if (tryBeacon(body)) return;
|
|
217
674
|
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
218
675
|
if (typeof fetchImpl !== "function") {
|
|
219
676
|
throw new Error("fetch_unavailable");
|
|
@@ -230,26 +687,22 @@ function createDeliveryManager(config) {
|
|
|
230
687
|
return {
|
|
231
688
|
async send(payload) {
|
|
232
689
|
const body = withEnvelope(payload);
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
messageId: String(body.messageId),
|
|
236
|
-
reason: "payload_too_large",
|
|
237
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
238
|
-
});
|
|
690
|
+
const preparedBody = preparePayloadForSend(body);
|
|
691
|
+
if (!preparedBody) {
|
|
239
692
|
return;
|
|
240
693
|
}
|
|
241
694
|
diagnostics.inFlight += 1;
|
|
242
695
|
try {
|
|
243
|
-
await deliver(
|
|
696
|
+
await deliver(preparedBody);
|
|
244
697
|
} catch (error) {
|
|
245
698
|
const deliveryError = error instanceof Error ? error : new Error(String(error));
|
|
246
699
|
recordError(deliveryError);
|
|
247
700
|
enqueue({
|
|
248
|
-
messageId: String(body
|
|
701
|
+
messageId: String(getPayloadMessageId(body)),
|
|
249
702
|
savedAt: Date.now(),
|
|
250
703
|
attempts: 1,
|
|
251
704
|
lastError: deliveryError.message,
|
|
252
|
-
payload:
|
|
705
|
+
payload: preparedBody
|
|
253
706
|
});
|
|
254
707
|
} finally {
|
|
255
708
|
diagnostics.inFlight -= 1;
|
|
@@ -362,65 +815,109 @@ function createDeliveryManager(config) {
|
|
|
362
815
|
};
|
|
363
816
|
}
|
|
364
817
|
|
|
365
|
-
// src/browser/core/
|
|
366
|
-
var
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
"name",
|
|
376
|
-
"token",
|
|
377
|
-
"secret",
|
|
378
|
-
"password",
|
|
379
|
-
"session",
|
|
380
|
-
"cookie"
|
|
381
|
-
]);
|
|
382
|
-
function sanitizeValue(value, allow) {
|
|
383
|
-
if (Array.isArray(value)) {
|
|
384
|
-
return value.map((item) => sanitizeValue(item, allow));
|
|
818
|
+
// src/browser/core/identity.ts
|
|
819
|
+
var ANONYMOUS_ID_STORAGE_KEY = "dmd_anonymous_id";
|
|
820
|
+
var LEGACY_ANONYMOUS_ID_STORAGE_KEY = "anonymousId";
|
|
821
|
+
function getUrlParam(name) {
|
|
822
|
+
const href = getBrowserWindow()?.location?.href;
|
|
823
|
+
if (!href) return null;
|
|
824
|
+
try {
|
|
825
|
+
return new URL(href).searchParams.get(name);
|
|
826
|
+
} catch {
|
|
827
|
+
return null;
|
|
385
828
|
}
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
829
|
+
}
|
|
830
|
+
function resolveAnonymousId(persistence) {
|
|
831
|
+
const urlAnonymousId = getUrlParam("aid");
|
|
832
|
+
if (isUuid(urlAnonymousId)) {
|
|
833
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, urlAnonymousId);
|
|
834
|
+
return urlAnonymousId;
|
|
390
835
|
}
|
|
391
|
-
|
|
836
|
+
const storedAnonymousId = persistence.getItem(ANONYMOUS_ID_STORAGE_KEY);
|
|
837
|
+
if (isUuid(storedAnonymousId)) {
|
|
838
|
+
return storedAnonymousId;
|
|
839
|
+
}
|
|
840
|
+
const legacyAnonymousId = persistence.getItem(LEGACY_ANONYMOUS_ID_STORAGE_KEY);
|
|
841
|
+
if (isUuid(legacyAnonymousId)) {
|
|
842
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, legacyAnonymousId);
|
|
843
|
+
return legacyAnonymousId;
|
|
844
|
+
}
|
|
845
|
+
const anonymousId = createUuid();
|
|
846
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
847
|
+
return anonymousId;
|
|
392
848
|
}
|
|
393
|
-
function
|
|
394
|
-
const
|
|
395
|
-
|
|
849
|
+
function resetAnonymousId(persistence) {
|
|
850
|
+
const anonymousId = createUuid();
|
|
851
|
+
persistence.setItem(ANONYMOUS_ID_STORAGE_KEY, anonymousId);
|
|
852
|
+
return anonymousId;
|
|
396
853
|
}
|
|
397
854
|
|
|
398
|
-
// src/browser/core/
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
855
|
+
// src/browser/core/persistence.ts
|
|
856
|
+
function createPersistenceHealth(requested) {
|
|
857
|
+
return {
|
|
858
|
+
requested,
|
|
859
|
+
cookieFallbackUsed: false,
|
|
860
|
+
memoryFallbackUsed: requested === "memory",
|
|
861
|
+
failures: []
|
|
862
|
+
};
|
|
863
|
+
}
|
|
864
|
+
function recordFailure(health, backend, operation, error) {
|
|
865
|
+
health.failures.push({
|
|
866
|
+
backend,
|
|
867
|
+
operation,
|
|
868
|
+
message: error instanceof Error ? error.message : String(error)
|
|
869
|
+
});
|
|
870
|
+
if (health.failures.length > 25) {
|
|
871
|
+
health.failures.shift();
|
|
411
872
|
}
|
|
412
|
-
return { ok: errors.length === 0, errors };
|
|
413
873
|
}
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
874
|
+
function createMemoryPersistence(health = createPersistenceHealth("memory")) {
|
|
875
|
+
const memory = {};
|
|
876
|
+
return {
|
|
877
|
+
getItem(key) {
|
|
878
|
+
return Object.prototype.hasOwnProperty.call(memory, key) ? memory[key] ?? null : null;
|
|
879
|
+
},
|
|
880
|
+
setItem(key, value) {
|
|
881
|
+
memory[key] = value;
|
|
882
|
+
return true;
|
|
883
|
+
},
|
|
884
|
+
removeItem(key) {
|
|
885
|
+
delete memory[key];
|
|
886
|
+
},
|
|
887
|
+
getHealth() {
|
|
888
|
+
return {
|
|
889
|
+
...health,
|
|
890
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
};
|
|
418
894
|
}
|
|
419
|
-
function
|
|
420
|
-
const
|
|
421
|
-
|
|
895
|
+
function getCookie2(name) {
|
|
896
|
+
const browserWindow = getBrowserWindow();
|
|
897
|
+
const cookie = browserWindow?.document?.cookie;
|
|
898
|
+
if (!cookie) return null;
|
|
899
|
+
const escapedName = name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
900
|
+
const match = new RegExp(`(?:^|; )${escapedName}=([^;]*)`).exec(cookie);
|
|
901
|
+
return match ? decodeURIComponent(match[1] ?? "") : null;
|
|
902
|
+
}
|
|
903
|
+
function setCookie(name, value) {
|
|
904
|
+
const browserWindow = getBrowserWindow();
|
|
905
|
+
if (!browserWindow?.document) return false;
|
|
906
|
+
try {
|
|
907
|
+
const expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1e3).toUTCString();
|
|
908
|
+
const secure = browserWindow.location?.protocol === "https:" ? "; Secure" : "";
|
|
909
|
+
browserWindow.document.cookie = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${secure}; SameSite=Lax`;
|
|
910
|
+
return true;
|
|
911
|
+
} catch {
|
|
912
|
+
return false;
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
function removeCookie(name) {
|
|
916
|
+
const browserWindow = getBrowserWindow();
|
|
917
|
+
if (!browserWindow?.document) return;
|
|
918
|
+
browserWindow.document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`;
|
|
422
919
|
}
|
|
423
|
-
function
|
|
920
|
+
function getLocalStorage() {
|
|
424
921
|
const browserWindow = getBrowserWindow();
|
|
425
922
|
try {
|
|
426
923
|
return browserWindow?.localStorage;
|
|
@@ -428,37 +925,209 @@ function getBrowserStorage() {
|
|
|
428
925
|
return void 0;
|
|
429
926
|
}
|
|
430
927
|
}
|
|
928
|
+
function getSessionStorage() {
|
|
929
|
+
const browserWindow = getBrowserWindow();
|
|
930
|
+
try {
|
|
931
|
+
return browserWindow?.sessionStorage;
|
|
932
|
+
} catch {
|
|
933
|
+
return void 0;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
function createBrowserPersistence(mode = "localStorage+cookie") {
|
|
937
|
+
const health = createPersistenceHealth(mode);
|
|
938
|
+
const memory = createMemoryPersistence(health);
|
|
939
|
+
if (mode === "none") {
|
|
940
|
+
return {
|
|
941
|
+
getItem() {
|
|
942
|
+
return null;
|
|
943
|
+
},
|
|
944
|
+
setItem() {
|
|
945
|
+
return false;
|
|
946
|
+
},
|
|
947
|
+
removeItem() {
|
|
948
|
+
},
|
|
949
|
+
getHealth() {
|
|
950
|
+
return {
|
|
951
|
+
...health,
|
|
952
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
if (mode === "memory") return memory;
|
|
958
|
+
const primary = mode === "sessionStorage" ? getSessionStorage() : getLocalStorage();
|
|
959
|
+
const useCookie = mode === "cookie" || mode === "localStorage+cookie" || !primary;
|
|
960
|
+
return {
|
|
961
|
+
getItem(key) {
|
|
962
|
+
try {
|
|
963
|
+
const stored = primary?.getItem(key);
|
|
964
|
+
if (stored) return stored;
|
|
965
|
+
} catch (error) {
|
|
966
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "get", error);
|
|
967
|
+
}
|
|
968
|
+
if (useCookie) {
|
|
969
|
+
const cookie = getCookie2(key);
|
|
970
|
+
if (cookie) {
|
|
971
|
+
health.cookieFallbackUsed = true;
|
|
972
|
+
return cookie;
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
const value = memory.getItem(key);
|
|
976
|
+
if (value !== null) health.memoryFallbackUsed = true;
|
|
977
|
+
return value;
|
|
978
|
+
},
|
|
979
|
+
setItem(key, value) {
|
|
980
|
+
let wrote = false;
|
|
981
|
+
try {
|
|
982
|
+
primary?.setItem(key, value);
|
|
983
|
+
wrote = primary !== void 0;
|
|
984
|
+
} catch (error) {
|
|
985
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "set", error);
|
|
986
|
+
wrote = false;
|
|
987
|
+
}
|
|
988
|
+
if (useCookie) {
|
|
989
|
+
const cookieWrote = setCookie(key, value);
|
|
990
|
+
if (cookieWrote) health.cookieFallbackUsed = true;
|
|
991
|
+
wrote = cookieWrote || wrote;
|
|
992
|
+
}
|
|
993
|
+
if (!wrote) {
|
|
994
|
+
health.memoryFallbackUsed = true;
|
|
995
|
+
return memory.setItem(key, value);
|
|
996
|
+
}
|
|
997
|
+
if (mode === "localStorage+cookie") {
|
|
998
|
+
memory.setItem(key, value);
|
|
999
|
+
}
|
|
1000
|
+
return true;
|
|
1001
|
+
},
|
|
1002
|
+
removeItem(key) {
|
|
1003
|
+
try {
|
|
1004
|
+
primary?.removeItem(key);
|
|
1005
|
+
} catch (error) {
|
|
1006
|
+
recordFailure(health, mode === "sessionStorage" ? "sessionStorage" : "localStorage", "remove", error);
|
|
1007
|
+
}
|
|
1008
|
+
if (useCookie) removeCookie(key);
|
|
1009
|
+
memory.removeItem(key);
|
|
1010
|
+
},
|
|
1011
|
+
getHealth() {
|
|
1012
|
+
return {
|
|
1013
|
+
...health,
|
|
1014
|
+
failures: health.failures.map((failure) => ({ ...failure }))
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
1017
|
+
};
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// src/browser/core/session.ts
|
|
1021
|
+
var SESSION_STORAGE_KEY = "sessionData";
|
|
1022
|
+
function getUrlParam2(name) {
|
|
1023
|
+
const href = getBrowserWindow()?.location?.href;
|
|
1024
|
+
if (!href) return null;
|
|
1025
|
+
try {
|
|
1026
|
+
return new URL(href).searchParams.get(name);
|
|
1027
|
+
} catch {
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function readStoredSession(persistence) {
|
|
1032
|
+
const rawSession = persistence.getItem(SESSION_STORAGE_KEY);
|
|
1033
|
+
if (!rawSession) return void 0;
|
|
1034
|
+
try {
|
|
1035
|
+
const parsed = JSON.parse(rawSession);
|
|
1036
|
+
if (isUuid(parsed.sessionId) && typeof parsed.timestamp === "number") {
|
|
1037
|
+
return {
|
|
1038
|
+
sessionId: parsed.sessionId,
|
|
1039
|
+
timestamp: parsed.timestamp
|
|
1040
|
+
};
|
|
1041
|
+
}
|
|
1042
|
+
} catch {
|
|
1043
|
+
persistence.removeItem(SESSION_STORAGE_KEY);
|
|
1044
|
+
}
|
|
1045
|
+
return void 0;
|
|
1046
|
+
}
|
|
1047
|
+
function writeStoredSession(persistence, sessionId, timestamp) {
|
|
1048
|
+
persistence.setItem(SESSION_STORAGE_KEY, JSON.stringify({ sessionId, timestamp }));
|
|
1049
|
+
}
|
|
1050
|
+
function createSessionManager(persistence, idleTimeoutSeconds = 30 * 60) {
|
|
1051
|
+
function resolveSessionId() {
|
|
1052
|
+
const now = Date.now();
|
|
1053
|
+
const urlSessionId = getUrlParam2("sid") ?? getUrlParam2("session_id");
|
|
1054
|
+
if (isUuid(urlSessionId)) {
|
|
1055
|
+
writeStoredSession(persistence, urlSessionId, now);
|
|
1056
|
+
return urlSessionId;
|
|
1057
|
+
}
|
|
1058
|
+
const storedSession = readStoredSession(persistence);
|
|
1059
|
+
if (storedSession && now - storedSession.timestamp <= idleTimeoutSeconds * 1e3) {
|
|
1060
|
+
writeStoredSession(persistence, storedSession.sessionId, now);
|
|
1061
|
+
return storedSession.sessionId;
|
|
1062
|
+
}
|
|
1063
|
+
const sessionId = createUuid();
|
|
1064
|
+
writeStoredSession(persistence, sessionId, now);
|
|
1065
|
+
return sessionId;
|
|
1066
|
+
}
|
|
1067
|
+
return {
|
|
1068
|
+
getSessionId() {
|
|
1069
|
+
return resolveSessionId();
|
|
1070
|
+
},
|
|
1071
|
+
reset() {
|
|
1072
|
+
const sessionId = createUuid();
|
|
1073
|
+
writeStoredSession(persistence, sessionId, Date.now());
|
|
1074
|
+
return sessionId;
|
|
1075
|
+
}
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
// src/browser/core/DriveMetaDataSDK.ts
|
|
1080
|
+
function endpointFromConfig(config) {
|
|
1081
|
+
const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
|
|
1082
|
+
return `${host.replace(/\/$/, "")}/data-collector`;
|
|
1083
|
+
}
|
|
1084
|
+
function requireConfigString(value, field) {
|
|
1085
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
1086
|
+
throw new Error(`DMD SDK config ${field} is required`);
|
|
1087
|
+
}
|
|
1088
|
+
return value;
|
|
1089
|
+
}
|
|
431
1090
|
var DriveMetaDataSDK = class {
|
|
432
1091
|
constructor(config) {
|
|
433
1092
|
this.initialized = true;
|
|
434
1093
|
this.queue = [];
|
|
435
1094
|
this.offline = false;
|
|
436
1095
|
this.droppedEvents = 0;
|
|
1096
|
+
requireConfigString(config.clientId, "clientId");
|
|
1097
|
+
requireConfigString(config.workspaceId, "workspaceId");
|
|
1098
|
+
requireConfigString(config.appId, "appId");
|
|
1099
|
+
requireConfigString(config.writeKey || config.token, "writeKey or token");
|
|
437
1100
|
this.config = config;
|
|
438
1101
|
this.endpoint = endpointFromConfig(config);
|
|
439
|
-
|
|
1102
|
+
this.persistence = createBrowserPersistence(config.persistence);
|
|
1103
|
+
this.session = createSessionManager(this.persistence, config.sessionIdleTimeoutSeconds);
|
|
440
1104
|
const deliveryConfig = {
|
|
441
|
-
endpoint: this.endpoint
|
|
1105
|
+
endpoint: this.endpoint,
|
|
1106
|
+
storage: this.persistence
|
|
442
1107
|
};
|
|
443
1108
|
if (config.delivery?.maxQueueSize !== void 0) deliveryConfig.maxQueueSize = config.delivery.maxQueueSize;
|
|
444
1109
|
if (config.delivery?.queueTtlMs !== void 0) deliveryConfig.queueTtlMs = config.delivery.queueTtlMs;
|
|
445
1110
|
if (config.delivery?.retryDelayMs !== void 0) deliveryConfig.retryDelayMs = config.delivery.retryDelayMs;
|
|
446
1111
|
if (config.delivery?.maxRetryDelayMs !== void 0) deliveryConfig.maxRetryDelayMs = config.delivery.maxRetryDelayMs;
|
|
447
1112
|
if (config.delivery?.maxPayloadBytes !== void 0) deliveryConfig.maxPayloadBytes = config.delivery.maxPayloadBytes;
|
|
1113
|
+
if (config.delivery?.payloadSizePolicy !== void 0) deliveryConfig.payloadSizePolicy = config.delivery.payloadSizePolicy;
|
|
1114
|
+
if (config.delivery?.payloadTruncateStringLength !== void 0) {
|
|
1115
|
+
deliveryConfig.payloadTruncateStringLength = config.delivery.payloadTruncateStringLength;
|
|
1116
|
+
}
|
|
1117
|
+
if (config.delivery?.useBeacon !== void 0) deliveryConfig.useBeacon = config.delivery.useBeacon;
|
|
448
1118
|
if (config.delivery?.batchSize !== void 0) deliveryConfig.batchSize = config.delivery.batchSize;
|
|
449
1119
|
if (config.onDrop !== void 0) deliveryConfig.onDrop = config.onDrop;
|
|
450
1120
|
if (config.onError !== void 0) deliveryConfig.onError = config.onError;
|
|
451
|
-
this.delivery = createDeliveryManager(
|
|
452
|
-
...deliveryConfig,
|
|
453
|
-
storage
|
|
454
|
-
} : deliveryConfig);
|
|
1121
|
+
this.delivery = createDeliveryManager(deliveryConfig);
|
|
455
1122
|
this.initialRetryDelayMs = config.delivery?.retryDelayMs ?? 1e3;
|
|
456
1123
|
this.retryDelayMs = this.initialRetryDelayMs;
|
|
457
1124
|
this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
|
|
458
1125
|
this.writeKey = config.writeKey || config.token || "";
|
|
459
|
-
this.identity = { anonymousId:
|
|
1126
|
+
this.identity = { anonymousId: resolveAnonymousId(this.persistence) };
|
|
1127
|
+
captureAttributionFromUrl(this.persistence);
|
|
460
1128
|
this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
|
|
461
1129
|
this.gdprConsent = this.consentState.analytics;
|
|
1130
|
+
this.installAutocapture();
|
|
462
1131
|
if (!config.delivery?.disableLifecycleFlush) {
|
|
463
1132
|
this.installLifecycleFlush();
|
|
464
1133
|
}
|
|
@@ -498,7 +1167,8 @@ var DriveMetaDataSDK = class {
|
|
|
498
1167
|
}
|
|
499
1168
|
}
|
|
500
1169
|
reset() {
|
|
501
|
-
this.identity = { anonymousId:
|
|
1170
|
+
this.identity = { anonymousId: resetAnonymousId(this.persistence) };
|
|
1171
|
+
this.session.reset();
|
|
502
1172
|
this.queue = [];
|
|
503
1173
|
this.offline = false;
|
|
504
1174
|
if (this.retryTimer !== void 0) {
|
|
@@ -507,8 +1177,20 @@ var DriveMetaDataSDK = class {
|
|
|
507
1177
|
}
|
|
508
1178
|
this.lifecycleCleanup?.();
|
|
509
1179
|
this.lifecycleCleanup = void 0;
|
|
1180
|
+
this.autocaptureCleanup?.();
|
|
1181
|
+
this.autocaptureCleanup = void 0;
|
|
510
1182
|
this.delivery.clearQueue("manual_clear");
|
|
511
1183
|
}
|
|
1184
|
+
disposeForTests() {
|
|
1185
|
+
if (this.retryTimer !== void 0) {
|
|
1186
|
+
clearTimeout(this.retryTimer);
|
|
1187
|
+
this.retryTimer = void 0;
|
|
1188
|
+
}
|
|
1189
|
+
this.lifecycleCleanup?.();
|
|
1190
|
+
this.lifecycleCleanup = void 0;
|
|
1191
|
+
this.autocaptureCleanup?.();
|
|
1192
|
+
this.autocaptureCleanup = void 0;
|
|
1193
|
+
}
|
|
512
1194
|
setConsent(consent2) {
|
|
513
1195
|
this.consentState = typeof consent2 === "object" ? mergeConsent(this.consentState, consent2) : normalizeConsent(consent2);
|
|
514
1196
|
this.gdprConsent = this.consentState.analytics;
|
|
@@ -523,6 +1205,7 @@ var DriveMetaDataSDK = class {
|
|
|
523
1205
|
initialized: this.initialized,
|
|
524
1206
|
consent: this.gdprConsent,
|
|
525
1207
|
consentPurposes: this.consentState,
|
|
1208
|
+
persistence: this.persistence.getHealth(),
|
|
526
1209
|
queueSize: deliveryDiagnostics.queued,
|
|
527
1210
|
offline: this.offline || deliveryDiagnostics.queued > 0,
|
|
528
1211
|
droppedEvents: this.droppedEvents + deliveryDiagnostics.dropped.length,
|
|
@@ -537,7 +1220,9 @@ var DriveMetaDataSDK = class {
|
|
|
537
1220
|
void this.delivery.send(payload).then(() => {
|
|
538
1221
|
const diagnostics = this.delivery.getDiagnostics();
|
|
539
1222
|
this.offline = diagnostics.queued > 0;
|
|
540
|
-
|
|
1223
|
+
if (diagnostics.lastError !== void 0) {
|
|
1224
|
+
this.lastError = diagnostics.lastError;
|
|
1225
|
+
}
|
|
541
1226
|
if (diagnostics.queued > 0) {
|
|
542
1227
|
this.scheduleRetryFlush();
|
|
543
1228
|
}
|
|
@@ -569,6 +1254,28 @@ var DriveMetaDataSDK = class {
|
|
|
569
1254
|
}
|
|
570
1255
|
};
|
|
571
1256
|
}
|
|
1257
|
+
installAutocapture() {
|
|
1258
|
+
const browserWindow = getBrowserWindow();
|
|
1259
|
+
if (!browserWindow) return;
|
|
1260
|
+
if (this.config.autocapture === false) return;
|
|
1261
|
+
const capturePageview = this.config.capturePageview !== false;
|
|
1262
|
+
const capturePageleave = this.config.capturePageleave !== false;
|
|
1263
|
+
const controller = installAutocapture({
|
|
1264
|
+
browserWindow,
|
|
1265
|
+
capturePageview,
|
|
1266
|
+
capturePageleave,
|
|
1267
|
+
onPageView: () => {
|
|
1268
|
+
this.page();
|
|
1269
|
+
},
|
|
1270
|
+
onPageLeave: () => {
|
|
1271
|
+
this.trackEvent("page_leave", { url: browserWindow.location.href });
|
|
1272
|
+
},
|
|
1273
|
+
onRouteChange: () => {
|
|
1274
|
+
captureAttributionFromUrl(this.persistence);
|
|
1275
|
+
}
|
|
1276
|
+
});
|
|
1277
|
+
this.autocaptureCleanup = controller.cleanup;
|
|
1278
|
+
}
|
|
572
1279
|
scheduleRetryFlush() {
|
|
573
1280
|
if (this.retryTimer !== void 0) return;
|
|
574
1281
|
const delay = Math.min(this.retryDelayMs, this.maxRetryDelayMs);
|
|
@@ -594,7 +1301,7 @@ var DriveMetaDataSDK = class {
|
|
|
594
1301
|
type,
|
|
595
1302
|
event,
|
|
596
1303
|
properties: sanitizeProperties(properties),
|
|
597
|
-
messageId: options.messageId
|
|
1304
|
+
messageId: ensureUuid(options.messageId),
|
|
598
1305
|
timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
599
1306
|
context: options.context ?? {},
|
|
600
1307
|
anonymousId: this.identity.anonymousId,
|
|
@@ -602,7 +1309,8 @@ var DriveMetaDataSDK = class {
|
|
|
602
1309
|
workspaceId: this.config.workspaceId,
|
|
603
1310
|
appId: this.config.appId,
|
|
604
1311
|
writeKey: this.writeKey,
|
|
605
|
-
consent: this.consentState
|
|
1312
|
+
consent: this.consentState,
|
|
1313
|
+
sessionId: this.session.getSessionId()
|
|
606
1314
|
};
|
|
607
1315
|
if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
|
|
608
1316
|
if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
|
|
@@ -626,7 +1334,41 @@ var DriveMetaDataSDK = class {
|
|
|
626
1334
|
if (!validation.ok) {
|
|
627
1335
|
this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
|
|
628
1336
|
}
|
|
629
|
-
this.
|
|
1337
|
+
const collectorPayload = this.toCollectorPayload(prepared);
|
|
1338
|
+
const backendValidation = validateBackendCollectorPayload(collectorPayload);
|
|
1339
|
+
if (!backendValidation.ok && this.config.schemaValidation === "strict") {
|
|
1340
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1341
|
+
this.recordDrop(type, "invalid_payload", event);
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
if (!backendValidation.ok) {
|
|
1345
|
+
this.lastError = `DMD SDK backend schema warning: ${backendValidation.errors.join(", ")}`;
|
|
1346
|
+
}
|
|
1347
|
+
this.sendEvent(collectorPayload);
|
|
1348
|
+
}
|
|
1349
|
+
toCollectorPayload(prepared) {
|
|
1350
|
+
const browserWindow = getBrowserWindow();
|
|
1351
|
+
return createBackendCollectorPayload({
|
|
1352
|
+
requestId: prepared.messageId,
|
|
1353
|
+
timestamp: prepared.timestamp,
|
|
1354
|
+
eventType: prepared.event,
|
|
1355
|
+
clientId: prepared.clientId,
|
|
1356
|
+
workspaceId: prepared.workspaceId,
|
|
1357
|
+
token: prepared.writeKey,
|
|
1358
|
+
anonymousId: prepared.anonymousId,
|
|
1359
|
+
sessionId: prepared.sessionId,
|
|
1360
|
+
ua: browserWindow?.navigator?.userAgent,
|
|
1361
|
+
appId: prepared.appId,
|
|
1362
|
+
pageUrl: browserWindow?.location?.href,
|
|
1363
|
+
eventData: mergeStoredAttribution({
|
|
1364
|
+
...prepared.properties,
|
|
1365
|
+
anonymousId: prepared.anonymousId,
|
|
1366
|
+
sessionId: prepared.sessionId,
|
|
1367
|
+
timestamp: prepared.timestamp,
|
|
1368
|
+
requestSentAt: prepared.timestamp,
|
|
1369
|
+
requestReceivedAt: prepared.timestamp
|
|
1370
|
+
}, this.persistence)
|
|
1371
|
+
});
|
|
630
1372
|
}
|
|
631
1373
|
recordDrop(type, reason, event) {
|
|
632
1374
|
this.droppedEvents += 1;
|
|
@@ -640,22 +1382,6 @@ var DriveMetaDataSDK = class {
|
|
|
640
1382
|
}
|
|
641
1383
|
};
|
|
642
1384
|
|
|
643
|
-
// src/browser/legacy-loader.ts
|
|
644
|
-
function getLegacySdkInstanceFromWindow() {
|
|
645
|
-
const browserWindow = getBrowserWindow();
|
|
646
|
-
return browserWindow?.__DriveMetaDataSDKInstance;
|
|
647
|
-
}
|
|
648
|
-
function ensureLegacySdkLoaded() {
|
|
649
|
-
if (!isBrowserRuntime()) {
|
|
650
|
-
throw new Error("DMD legacy SDK is only available in a browser runtime");
|
|
651
|
-
}
|
|
652
|
-
const browserWindow = getBrowserWindow();
|
|
653
|
-
if (!browserWindow?.DriveMetaDataSDK) {
|
|
654
|
-
throw new Error("DMD legacy SDK constructor is missing from window.DriveMetaDataSDK");
|
|
655
|
-
}
|
|
656
|
-
return browserWindow.DriveMetaDataSDK;
|
|
657
|
-
}
|
|
658
|
-
|
|
659
1385
|
// src/browser/client.ts
|
|
660
1386
|
var singleton;
|
|
661
1387
|
var publicSingleton;
|
|
@@ -664,56 +1390,34 @@ var lastError;
|
|
|
664
1390
|
var lastDroppedEvent;
|
|
665
1391
|
function createPublicClient(instance) {
|
|
666
1392
|
return {
|
|
667
|
-
__legacy: instance,
|
|
668
1393
|
track(event, properties, options) {
|
|
669
|
-
|
|
670
|
-
instance.trackEvent(event, properties, options);
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
instance.sendEvent?.({ eventName: event, event, properties, options });
|
|
1394
|
+
instance.trackEvent(event, properties, options);
|
|
674
1395
|
},
|
|
675
1396
|
identify(userId, traits, options) {
|
|
676
|
-
|
|
677
|
-
instance.identify(userId, traits, options);
|
|
678
|
-
return;
|
|
679
|
-
}
|
|
680
|
-
instance.identifyUser?.(userId, traits);
|
|
1397
|
+
instance.identify(userId, traits, options);
|
|
681
1398
|
},
|
|
682
1399
|
page(name, properties, options) {
|
|
683
|
-
|
|
684
|
-
instance.page(name, properties, options);
|
|
685
|
-
return;
|
|
686
|
-
}
|
|
687
|
-
instance.trackPageview?.();
|
|
1400
|
+
instance.page(name, properties, options);
|
|
688
1401
|
},
|
|
689
1402
|
group(groupId, traits, options) {
|
|
690
|
-
instance.group
|
|
1403
|
+
instance.group(groupId, traits, options);
|
|
691
1404
|
},
|
|
692
1405
|
alias(previousId, userId, options) {
|
|
693
|
-
instance.alias
|
|
1406
|
+
instance.alias(previousId, userId, options);
|
|
694
1407
|
},
|
|
695
1408
|
async flush() {
|
|
696
|
-
await instance.flush
|
|
1409
|
+
await instance.flush();
|
|
697
1410
|
},
|
|
698
1411
|
reset() {
|
|
699
|
-
instance.reset
|
|
1412
|
+
instance.reset();
|
|
700
1413
|
singleton = void 0;
|
|
701
1414
|
publicSingleton = void 0;
|
|
702
1415
|
},
|
|
703
1416
|
setConsent(consent2) {
|
|
704
|
-
|
|
705
|
-
instance.setConsent(consent2);
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
if (typeof consent2 === "string") {
|
|
709
|
-
instance.gdprConsent = consent2;
|
|
710
|
-
}
|
|
1417
|
+
instance.setConsent(consent2);
|
|
711
1418
|
},
|
|
712
1419
|
getHealth() {
|
|
713
|
-
|
|
714
|
-
return instance.getHealth();
|
|
715
|
-
}
|
|
716
|
-
return getDmdHealth();
|
|
1420
|
+
return instance.getHealth();
|
|
717
1421
|
}
|
|
718
1422
|
};
|
|
719
1423
|
}
|
|
@@ -738,23 +1442,8 @@ function initDmdSDK(config) {
|
|
|
738
1442
|
if (publicSingleton) {
|
|
739
1443
|
return publicSingleton;
|
|
740
1444
|
}
|
|
741
|
-
const legacyConfig = normalizeBrowserConfig(config);
|
|
742
|
-
const existingInstance = getLegacySdkInstanceFromWindow();
|
|
743
|
-
if (existingInstance) {
|
|
744
|
-
return setSingleton(existingInstance);
|
|
745
|
-
}
|
|
746
1445
|
try {
|
|
747
|
-
|
|
748
|
-
try {
|
|
749
|
-
const LegacySdk = ensureLegacySdkLoaded();
|
|
750
|
-
instance = new LegacySdk(legacyConfig);
|
|
751
|
-
} catch (error) {
|
|
752
|
-
if (error instanceof Error && error.message.includes("constructor is missing")) {
|
|
753
|
-
instance = new DriveMetaDataSDK(config);
|
|
754
|
-
} else {
|
|
755
|
-
throw error;
|
|
756
|
-
}
|
|
757
|
-
}
|
|
1446
|
+
const instance = new DriveMetaDataSDK(normalizeBrowserConfig(config));
|
|
758
1447
|
return setSingleton(instance);
|
|
759
1448
|
} catch (error) {
|
|
760
1449
|
lastError = error instanceof Error ? error.message : String(error);
|
|
@@ -829,14 +1518,14 @@ async function ready() {
|
|
|
829
1518
|
return getDmdSDK();
|
|
830
1519
|
}
|
|
831
1520
|
function getDmdHealth() {
|
|
832
|
-
if (singleton
|
|
1521
|
+
if (singleton) {
|
|
833
1522
|
return singleton.getHealth();
|
|
834
1523
|
}
|
|
835
1524
|
const health = {
|
|
836
|
-
initialized:
|
|
837
|
-
consent:
|
|
838
|
-
queueSize:
|
|
839
|
-
offline:
|
|
1525
|
+
initialized: false,
|
|
1526
|
+
consent: "pending",
|
|
1527
|
+
queueSize: 0,
|
|
1528
|
+
offline: false,
|
|
840
1529
|
droppedEvents
|
|
841
1530
|
};
|
|
842
1531
|
if (lastError !== void 0) {
|
|
@@ -848,7 +1537,7 @@ function getDmdHealth() {
|
|
|
848
1537
|
return health;
|
|
849
1538
|
}
|
|
850
1539
|
function resetDmdSDKForTests() {
|
|
851
|
-
singleton?.
|
|
1540
|
+
singleton?.disposeForTests();
|
|
852
1541
|
singleton = void 0;
|
|
853
1542
|
publicSingleton = void 0;
|
|
854
1543
|
droppedEvents = 0;
|