@drivemetadata-ai/sdk 0.1.1-beta.1 → 0.1.1-beta.2

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.
Files changed (42) hide show
  1. package/README.md +18 -15
  2. package/dist/angular/index.cjs +118 -115
  3. package/dist/angular/index.cjs.map +1 -1
  4. package/dist/angular/index.d.cts +2 -2
  5. package/dist/angular/index.d.ts +2 -2
  6. package/dist/angular/index.js +118 -115
  7. package/dist/angular/index.js.map +1 -1
  8. package/dist/browser/index.cjs +119 -116
  9. package/dist/browser/index.cjs.map +1 -1
  10. package/dist/browser/index.d.cts +5 -68
  11. package/dist/browser/index.d.ts +5 -68
  12. package/dist/browser/index.js +119 -116
  13. package/dist/browser/index.js.map +1 -1
  14. package/dist/next/index.cjs +119 -115
  15. package/dist/next/index.cjs.map +1 -1
  16. package/dist/next/index.d.cts +1 -1
  17. package/dist/next/index.d.ts +1 -1
  18. package/dist/next/index.js +119 -115
  19. package/dist/next/index.js.map +1 -1
  20. package/dist/node/index.cjs +80 -7
  21. package/dist/node/index.cjs.map +1 -1
  22. package/dist/node/index.d.cts +7 -1
  23. package/dist/node/index.d.ts +7 -1
  24. package/dist/node/index.js +80 -7
  25. package/dist/node/index.js.map +1 -1
  26. package/dist/react/index.cjs +119 -115
  27. package/dist/react/index.cjs.map +1 -1
  28. package/dist/react/index.d.cts +2 -2
  29. package/dist/react/index.d.ts +2 -2
  30. package/dist/react/index.js +119 -115
  31. package/dist/react/index.js.map +1 -1
  32. package/dist/{types-BwtS0ZDu.d.cts → types--V8TVIqT.d.cts} +7 -3
  33. package/dist/{types-BwtS0ZDu.d.ts → types--V8TVIqT.d.ts} +7 -3
  34. package/docs/angular-integration.md +6 -6
  35. package/docs/index.md +4 -6
  36. package/docs/integration.md +322 -0
  37. package/docs/node-server-integration.md +16 -7
  38. package/docs/npm-browser-sdk.md +4 -8
  39. package/docs/react-next-integration.md +9 -9
  40. package/docs/security-privacy.md +11 -11
  41. package/package.json +4 -5
  42. package/docs/migration-cdn-to-npm.md +0 -99
@@ -1,53 +1,62 @@
1
1
  // src/react/DmdProvider.tsx
2
2
  import React from "react";
3
3
 
4
- // src/core/config.ts
5
- function requireString(value, field) {
6
- if (typeof value !== "string" || value.trim() === "") {
7
- throw new Error(`DMD SDK config ${field} is required`);
4
+ // src/core/backend-payload.ts
5
+ function formatUtcTimestamp(value) {
6
+ if (typeof value !== "string") return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
7
+ const date = new Date(value);
8
+ if (Number.isNaN(date.getTime())) return value;
9
+ return date.toISOString().replace("T", " ").slice(0, 19);
10
+ }
11
+ function cleanObject(value) {
12
+ if (Array.isArray(value)) {
13
+ const cleaned = value.map((item) => cleanObject(item)).filter((item) => item !== null && item !== void 0 && item !== "");
14
+ return cleaned.length > 0 ? cleaned : void 0;
15
+ }
16
+ if (value && typeof value === "object") {
17
+ const cleaned = Object.fromEntries(
18
+ Object.entries(value).map(([key, item]) => [key, cleanObject(item)]).filter(([, item]) => {
19
+ if (item === null || item === void 0 || item === "") return false;
20
+ if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 0) return false;
21
+ return true;
22
+ })
23
+ );
24
+ return Object.keys(cleaned).length > 0 ? cleaned : void 0;
8
25
  }
9
26
  return value;
10
27
  }
11
- function normalizeBrowserConfig(config) {
12
- const writeKey = config.writeKey || config.token;
13
- const legacyConfig = {
14
- client_id: requireString(config.clientId, "clientId"),
15
- workspace_id: requireString(config.workspaceId, "workspaceId"),
16
- app_id: requireString(config.appId, "appId"),
17
- token: requireString(writeKey, "writeKey")
28
+ function createBackendCollectorPayload(input) {
29
+ const eventData = input.eventData && typeof input.eventData === "object" ? input.eventData : {};
30
+ const page2 = eventData.page && typeof eventData.page === "object" ? eventData.page : {};
31
+ const timestamp = formatUtcTimestamp(eventData.timestamp ?? input.timestamp);
32
+ const normalizedEventData = {
33
+ ...eventData,
34
+ timestamp,
35
+ requestSentAt: formatUtcTimestamp(eventData.requestSentAt ?? input.requestSentAt ?? timestamp),
36
+ requestReceivedAt: formatUtcTimestamp(eventData.requestReceivedAt ?? input.requestReceivedAt ?? timestamp)
37
+ };
38
+ const metaData = {
39
+ ...normalizedEventData,
40
+ requestId: input.requestId,
41
+ timestamp,
42
+ eventType: input.eventType,
43
+ requestFrom: input.requestFrom ?? "3",
44
+ clientId: input.clientId,
45
+ workspaceId: input.workspaceId,
46
+ token: input.token,
47
+ anonymousId: eventData.anonymousId ?? input.anonymousId,
48
+ sessionId: eventData.sessionId ?? input.sessionId,
49
+ ua: input.ua,
50
+ appDetails: { app_id: input.appId },
51
+ page: { ...page2, url: page2.url ?? input.pageUrl },
52
+ requestSentAt: normalizedEventData.requestSentAt,
53
+ requestReceivedAt: normalizedEventData.requestReceivedAt
18
54
  };
19
- if (config.apiHost !== void 0) legacyConfig.api_host = config.apiHost;
20
- if (config.uiHost !== void 0) legacyConfig.ui_host = config.uiHost;
21
- if (config.deeplink !== void 0) legacyConfig.deeplink = config.deeplink;
22
- if (config.debug !== void 0) legacyConfig.debug = config.debug;
23
- if (config.consent !== void 0) legacyConfig.consent = config.consent;
24
- if (config.gdprConsent !== void 0) legacyConfig.gdprConsent = config.gdprConsent;
25
- if (config.autocapture !== void 0) legacyConfig.autocapture = config.autocapture;
26
- if (config.capturePageview !== void 0) legacyConfig.capture_pageview = config.capturePageview;
27
- if (config.capturePageleave !== void 0) legacyConfig.capture_pageleave = config.capturePageleave;
28
- if (config.captureDeadClicks !== void 0) legacyConfig.capture_dead_clicks = config.captureDeadClicks;
29
- if (config.crossSubdomainCookie !== void 0) legacyConfig.cross_subdomain_cookie = config.crossSubdomainCookie;
30
- if (config.disablePersistence !== void 0) legacyConfig.disable_persistence = config.disablePersistence;
31
- if (config.disableSurveys !== void 0) legacyConfig.disable_surveys = config.disableSurveys;
32
- if (config.disableSessionRecording !== void 0) legacyConfig.disable_session_recording = config.disableSessionRecording;
33
- if (config.enableHeatmaps !== void 0) legacyConfig.enable_heatmaps = config.enableHeatmaps;
34
- if (config.maskAllText !== void 0) legacyConfig.mask_all_text = config.maskAllText;
35
- if (config.maskAllElementAttributes !== void 0) {
36
- legacyConfig.mask_all_element_attributes = config.maskAllElementAttributes;
37
- }
38
- if (config.persistence !== void 0) legacyConfig.persistence = config.persistence;
39
- if (config.propertyDenylist !== void 0) legacyConfig.property_denylist = config.propertyDenylist;
40
- if (config.sessionIdleTimeoutSeconds !== void 0) {
41
- legacyConfig.session_idle_timeout_seconds = config.sessionIdleTimeoutSeconds;
42
- }
43
- if (config.beforeSend !== void 0) legacyConfig.before_send = config.beforeSend;
44
- return legacyConfig;
55
+ const payload = { metaData };
56
+ return cleanObject(payload);
45
57
  }
46
58
 
47
59
  // src/core/environment.ts
48
- function isBrowserRuntime() {
49
- return typeof window !== "undefined" && typeof document !== "undefined";
50
- }
51
60
  function getBrowserWindow() {
52
61
  return typeof window === "undefined" ? void 0 : window;
53
62
  }
@@ -107,8 +116,9 @@ function stableStringify(value) {
107
116
  );
108
117
  }
109
118
  function createIdempotencyKey(payload, messageId) {
110
- const event = String(payload.event ?? payload.type ?? "event");
111
- const properties = payload.properties;
119
+ const metaData = payload.metaData;
120
+ const event = String(metaData?.eventType ?? payload.event ?? payload.type ?? "event");
121
+ const properties = metaData ?? payload.properties;
112
122
  const orderId = properties?.orderId ?? properties?.order_id ?? properties?.transaction_id;
113
123
  if (orderId !== void 0) return `${event}:${String(orderId)}`;
114
124
  return `${event}:${stableStringify(properties ?? {}) || messageId}`;
@@ -209,7 +219,17 @@ function createDeliveryManager(config) {
209
219
  persistQueue();
210
220
  }
211
221
  function withEnvelope(payload) {
212
- const messageId = String(payload.messageId ?? createId("msg"));
222
+ const metaData = payload.metaData;
223
+ const messageId = String(metaData?.requestId ?? payload.messageId ?? createId("msg"));
224
+ if (metaData) {
225
+ return {
226
+ ...payload,
227
+ metaData: {
228
+ ...metaData,
229
+ requestId: messageId
230
+ }
231
+ };
232
+ }
213
233
  return {
214
234
  ...payload,
215
235
  messageId,
@@ -235,7 +255,7 @@ function createDeliveryManager(config) {
235
255
  const body = withEnvelope(payload);
236
256
  if (payloadByteLength(body) > maxPayloadBytes) {
237
257
  recordDrop({
238
- messageId: String(body.messageId),
258
+ messageId: String(body.metaData?.requestId ?? body.messageId),
239
259
  reason: "payload_too_large",
240
260
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
241
261
  });
@@ -248,7 +268,7 @@ function createDeliveryManager(config) {
248
268
  const deliveryError = error instanceof Error ? error : new Error(String(error));
249
269
  recordError(deliveryError);
250
270
  enqueue({
251
- messageId: String(body.messageId),
271
+ messageId: String(body.metaData?.requestId ?? body.messageId),
252
272
  savedAt: Date.now(),
253
273
  attempts: 1,
254
274
  lastError: deliveryError.message,
@@ -423,6 +443,12 @@ function endpointFromConfig(config) {
423
443
  const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
424
444
  return `${host.replace(/\/$/, "")}/data-collector`;
425
445
  }
446
+ function requireConfigString(value, field) {
447
+ if (typeof value !== "string" || value.trim() === "") {
448
+ throw new Error(`DMD SDK config ${field} is required`);
449
+ }
450
+ return value;
451
+ }
426
452
  function getBrowserStorage() {
427
453
  const browserWindow = getBrowserWindow();
428
454
  try {
@@ -437,6 +463,10 @@ var DriveMetaDataSDK = class {
437
463
  this.queue = [];
438
464
  this.offline = false;
439
465
  this.droppedEvents = 0;
466
+ requireConfigString(config.clientId, "clientId");
467
+ requireConfigString(config.workspaceId, "workspaceId");
468
+ requireConfigString(config.appId, "appId");
469
+ requireConfigString(config.writeKey || config.token, "writeKey or token");
440
470
  this.config = config;
441
471
  this.endpoint = endpointFromConfig(config);
442
472
  const storage = getBrowserStorage();
@@ -460,6 +490,7 @@ var DriveMetaDataSDK = class {
460
490
  this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
461
491
  this.writeKey = config.writeKey || config.token || "";
462
492
  this.identity = { anonymousId: createId2("anon") };
493
+ this.sessionId = createId2("session");
463
494
  this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
464
495
  this.gdprConsent = this.consentState.analytics;
465
496
  if (!config.delivery?.disableLifecycleFlush) {
@@ -605,7 +636,8 @@ var DriveMetaDataSDK = class {
605
636
  workspaceId: this.config.workspaceId,
606
637
  appId: this.config.appId,
607
638
  writeKey: this.writeKey,
608
- consent: this.consentState
639
+ consent: this.consentState,
640
+ sessionId: this.sessionId
609
641
  };
610
642
  if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
611
643
  if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
@@ -629,7 +661,31 @@ var DriveMetaDataSDK = class {
629
661
  if (!validation.ok) {
630
662
  this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
631
663
  }
632
- this.sendEvent(prepared);
664
+ this.sendEvent(this.toCollectorPayload(prepared));
665
+ }
666
+ toCollectorPayload(prepared) {
667
+ const browserWindow = getBrowserWindow();
668
+ return createBackendCollectorPayload({
669
+ requestId: prepared.messageId,
670
+ timestamp: prepared.timestamp,
671
+ eventType: prepared.event,
672
+ clientId: prepared.clientId,
673
+ workspaceId: prepared.workspaceId,
674
+ token: prepared.writeKey,
675
+ anonymousId: prepared.anonymousId,
676
+ sessionId: prepared.sessionId,
677
+ ua: browserWindow?.navigator?.userAgent,
678
+ appId: prepared.appId,
679
+ pageUrl: browserWindow?.location?.href,
680
+ eventData: {
681
+ ...prepared.properties,
682
+ anonymousId: prepared.anonymousId,
683
+ sessionId: prepared.sessionId,
684
+ timestamp: prepared.timestamp,
685
+ requestSentAt: prepared.timestamp,
686
+ requestReceivedAt: prepared.timestamp
687
+ }
688
+ });
633
689
  }
634
690
  recordDrop(type, reason, event) {
635
691
  this.droppedEvents += 1;
@@ -643,22 +699,6 @@ var DriveMetaDataSDK = class {
643
699
  }
644
700
  };
645
701
 
646
- // src/browser/legacy-loader.ts
647
- function getLegacySdkInstanceFromWindow() {
648
- const browserWindow = getBrowserWindow();
649
- return browserWindow?.__DriveMetaDataSDKInstance;
650
- }
651
- function ensureLegacySdkLoaded() {
652
- if (!isBrowserRuntime()) {
653
- throw new Error("DMD legacy SDK is only available in a browser runtime");
654
- }
655
- const browserWindow = getBrowserWindow();
656
- if (!browserWindow?.DriveMetaDataSDK) {
657
- throw new Error("DMD legacy SDK constructor is missing from window.DriveMetaDataSDK");
658
- }
659
- return browserWindow.DriveMetaDataSDK;
660
- }
661
-
662
702
  // src/browser/client.ts
663
703
  var singleton;
664
704
  var publicSingleton;
@@ -667,56 +707,34 @@ var lastError;
667
707
  var lastDroppedEvent;
668
708
  function createPublicClient(instance) {
669
709
  return {
670
- __legacy: instance,
671
710
  track(event, properties, options) {
672
- if (instance.trackEvent) {
673
- instance.trackEvent(event, properties, options);
674
- return;
675
- }
676
- instance.sendEvent?.({ eventName: event, event, properties, options });
711
+ instance.trackEvent(event, properties, options);
677
712
  },
678
713
  identify(userId, traits, options) {
679
- if (instance.identify) {
680
- instance.identify(userId, traits, options);
681
- return;
682
- }
683
- instance.identifyUser?.(userId, traits);
714
+ instance.identify(userId, traits, options);
684
715
  },
685
716
  page(name, properties, options) {
686
- if (instance.page) {
687
- instance.page(name, properties, options);
688
- return;
689
- }
690
- instance.trackPageview?.();
717
+ instance.page(name, properties, options);
691
718
  },
692
719
  group(groupId, traits, options) {
693
- instance.group?.(groupId, traits, options);
720
+ instance.group(groupId, traits, options);
694
721
  },
695
722
  alias(previousId, userId, options) {
696
- instance.alias?.(previousId, userId, options);
723
+ instance.alias(previousId, userId, options);
697
724
  },
698
725
  async flush() {
699
- await instance.flush?.();
726
+ await instance.flush();
700
727
  },
701
728
  reset() {
702
- instance.reset?.();
729
+ instance.reset();
703
730
  singleton = void 0;
704
731
  publicSingleton = void 0;
705
732
  },
706
733
  setConsent(consent) {
707
- if (instance.setConsent) {
708
- instance.setConsent(consent);
709
- return;
710
- }
711
- if (typeof consent === "string") {
712
- instance.gdprConsent = consent;
713
- }
734
+ instance.setConsent(consent);
714
735
  },
715
736
  getHealth() {
716
- if (instance.getHealth) {
717
- return instance.getHealth();
718
- }
719
- return getDmdHealth();
737
+ return instance.getHealth();
720
738
  }
721
739
  };
722
740
  }
@@ -741,23 +759,8 @@ function initDmdSDK(config) {
741
759
  if (publicSingleton) {
742
760
  return publicSingleton;
743
761
  }
744
- const legacyConfig = normalizeBrowserConfig(config);
745
- const existingInstance = getLegacySdkInstanceFromWindow();
746
- if (existingInstance) {
747
- return setSingleton(existingInstance);
748
- }
749
762
  try {
750
- let instance;
751
- try {
752
- const LegacySdk = ensureLegacySdkLoaded();
753
- instance = new LegacySdk(legacyConfig);
754
- } catch (error) {
755
- if (error instanceof Error && error.message.includes("constructor is missing")) {
756
- instance = new DriveMetaDataSDK(config);
757
- } else {
758
- throw error;
759
- }
760
- }
763
+ const instance = new DriveMetaDataSDK(config);
761
764
  return setSingleton(instance);
762
765
  } catch (error) {
763
766
  lastError = error instanceof Error ? error.message : String(error);
@@ -824,14 +827,14 @@ function setConsent(consent) {
824
827
  getDmdSDK()?.setConsent(consent);
825
828
  }
826
829
  function getDmdHealth() {
827
- if (singleton?.getHealth) {
830
+ if (singleton) {
828
831
  return singleton.getHealth();
829
832
  }
830
833
  const health = {
831
- initialized: Boolean(singleton?.initialized ?? singleton),
832
- consent: singleton?.gdprConsent ?? "pending",
833
- queueSize: singleton?.queue?.length ?? 0,
834
- offline: Boolean(singleton?.offline),
834
+ initialized: false,
835
+ consent: "pending",
836
+ queueSize: 0,
837
+ offline: false,
835
838
  droppedEvents
836
839
  };
837
840
  if (lastError !== void 0) {
@@ -874,6 +877,7 @@ function DmdProvider({
874
877
  config.workspaceId,
875
878
  config.appId,
876
879
  config.writeKey,
880
+ config.token,
877
881
  config.apiHost,
878
882
  config.consent,
879
883
  config.gdprConsent,