@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
package/README.md CHANGED
@@ -5,19 +5,19 @@ Enterprise-grade analytics, behavior intelligence, and customer data collection
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- npm install @drivemetadata/sdk
8
+ npm install @drivemetadata-ai/sdk
9
9
  ```
10
10
 
11
11
  ## Browser
12
12
 
13
13
  ```ts
14
- import { initDmdSDK } from '@drivemetadata/sdk/browser';
14
+ import { initDmdSDK } from '@drivemetadata-ai/sdk/browser';
15
15
 
16
16
  const dmd = initDmdSDK({
17
17
  clientId: 'client_xxx',
18
18
  workspaceId: 'workspace_xxx',
19
19
  appId: 'app_xxx',
20
- writeKey: 'public_write_key',
20
+ token: 'public_token',
21
21
  consent: {
22
22
  analytics: 'pending',
23
23
  advertising: 'denied',
@@ -37,7 +37,7 @@ await dmd.flush();
37
37
  ## React
38
38
 
39
39
  ```tsx
40
- import { DmdProvider, useTrackEvent } from '@drivemetadata/sdk/react';
40
+ import { DmdProvider, useTrackEvent } from '@drivemetadata-ai/sdk/react';
41
41
 
42
42
  function ProductButton() {
43
43
  const track = useTrackEvent();
@@ -55,27 +55,30 @@ export function App() {
55
55
 
56
56
  ## Next.js
57
57
 
58
- Use `@drivemetadata/sdk/next` from a client component.
58
+ Use `@drivemetadata-ai/sdk/next` from a client component.
59
59
 
60
60
  ```tsx
61
61
  'use client';
62
62
 
63
- import { DmdProvider } from '@drivemetadata/sdk/next';
63
+ import { DmdProvider } from '@drivemetadata-ai/sdk/next';
64
64
  ```
65
65
 
66
66
  ## Angular
67
67
 
68
68
  ```ts
69
- import { DmdAnalyticsService, provideDmdAnalytics } from '@drivemetadata/sdk/angular';
69
+ import { DmdAnalyticsService, provideDmdAnalytics } from '@drivemetadata-ai/sdk/angular';
70
70
  ```
71
71
 
72
72
  ## Node.js
73
73
 
74
74
  ```ts
75
- import { createDmdServerClient } from '@drivemetadata/sdk/node';
75
+ import { createDmdServerClient } from '@drivemetadata-ai/sdk/node';
76
76
 
77
77
  const dmd = createDmdServerClient({
78
- writeKey: process.env.DMD_SERVER_WRITE_KEY!
78
+ clientId: 'client_xxx',
79
+ workspaceId: 'workspace_xxx',
80
+ appId: 'app_xxx',
81
+ token: process.env.DMD_SERVER_TOKEN!
79
82
  });
80
83
 
81
84
  await dmd.track({
@@ -87,20 +90,20 @@ await dmd.track({
87
90
 
88
91
  ## Runtime Entries
89
92
 
90
- - `@drivemetadata/sdk/browser`
91
- - `@drivemetadata/sdk/react`
92
- - `@drivemetadata/sdk/next`
93
- - `@drivemetadata/sdk/angular`
94
- - `@drivemetadata/sdk/node`
93
+ - `@drivemetadata-ai/sdk/browser`
94
+ - `@drivemetadata-ai/sdk/react`
95
+ - `@drivemetadata-ai/sdk/next`
96
+ - `@drivemetadata-ai/sdk/angular`
97
+ - `@drivemetadata-ai/sdk/node`
95
98
 
96
99
  ## Documentation
97
100
 
101
+ - Complete integration guide: `docs/integration.md`
98
102
  - Browser npm SDK: `docs/npm-browser-sdk.md`
99
103
  - React and Next.js: `docs/react-next-integration.md`
100
104
  - Angular: `docs/angular-integration.md`
101
105
  - Node/server: `docs/node-server-integration.md`
102
106
  - Security and privacy: `docs/security-privacy.md`
103
- - CDN to npm migration: `docs/migration-cdn-to-npm.md`
104
107
 
105
108
  ## License
106
109
 
@@ -38,53 +38,62 @@ module.exports = __toCommonJS(angular_exports);
38
38
  // src/angular/dmd-analytics.service.ts
39
39
  var import_core2 = require("@angular/core");
40
40
 
41
- // src/core/config.ts
42
- function requireString(value, field) {
43
- if (typeof value !== "string" || value.trim() === "") {
44
- throw new Error(`DMD SDK config ${field} is required`);
41
+ // src/core/backend-payload.ts
42
+ function formatUtcTimestamp(value) {
43
+ if (typeof value !== "string") return (/* @__PURE__ */ new Date()).toISOString().replace("T", " ").slice(0, 19);
44
+ const date = new Date(value);
45
+ if (Number.isNaN(date.getTime())) return value;
46
+ return date.toISOString().replace("T", " ").slice(0, 19);
47
+ }
48
+ function cleanObject(value) {
49
+ if (Array.isArray(value)) {
50
+ const cleaned = value.map((item) => cleanObject(item)).filter((item) => item !== null && item !== void 0 && item !== "");
51
+ return cleaned.length > 0 ? cleaned : void 0;
52
+ }
53
+ if (value && typeof value === "object") {
54
+ const cleaned = Object.fromEntries(
55
+ Object.entries(value).map(([key, item]) => [key, cleanObject(item)]).filter(([, item]) => {
56
+ if (item === null || item === void 0 || item === "") return false;
57
+ if (typeof item === "object" && !Array.isArray(item) && Object.keys(item).length === 0) return false;
58
+ return true;
59
+ })
60
+ );
61
+ return Object.keys(cleaned).length > 0 ? cleaned : void 0;
45
62
  }
46
63
  return value;
47
64
  }
48
- function normalizeBrowserConfig(config) {
49
- const writeKey = config.writeKey || config.token;
50
- const legacyConfig = {
51
- client_id: requireString(config.clientId, "clientId"),
52
- workspace_id: requireString(config.workspaceId, "workspaceId"),
53
- app_id: requireString(config.appId, "appId"),
54
- token: requireString(writeKey, "writeKey")
65
+ function createBackendCollectorPayload(input) {
66
+ const eventData = input.eventData && typeof input.eventData === "object" ? input.eventData : {};
67
+ const page2 = eventData.page && typeof eventData.page === "object" ? eventData.page : {};
68
+ const timestamp = formatUtcTimestamp(eventData.timestamp ?? input.timestamp);
69
+ const normalizedEventData = {
70
+ ...eventData,
71
+ timestamp,
72
+ requestSentAt: formatUtcTimestamp(eventData.requestSentAt ?? input.requestSentAt ?? timestamp),
73
+ requestReceivedAt: formatUtcTimestamp(eventData.requestReceivedAt ?? input.requestReceivedAt ?? timestamp)
74
+ };
75
+ const metaData = {
76
+ ...normalizedEventData,
77
+ requestId: input.requestId,
78
+ timestamp,
79
+ eventType: input.eventType,
80
+ requestFrom: input.requestFrom ?? "3",
81
+ clientId: input.clientId,
82
+ workspaceId: input.workspaceId,
83
+ token: input.token,
84
+ anonymousId: eventData.anonymousId ?? input.anonymousId,
85
+ sessionId: eventData.sessionId ?? input.sessionId,
86
+ ua: input.ua,
87
+ appDetails: { app_id: input.appId },
88
+ page: { ...page2, url: page2.url ?? input.pageUrl },
89
+ requestSentAt: normalizedEventData.requestSentAt,
90
+ requestReceivedAt: normalizedEventData.requestReceivedAt
55
91
  };
56
- if (config.apiHost !== void 0) legacyConfig.api_host = config.apiHost;
57
- if (config.uiHost !== void 0) legacyConfig.ui_host = config.uiHost;
58
- if (config.deeplink !== void 0) legacyConfig.deeplink = config.deeplink;
59
- if (config.debug !== void 0) legacyConfig.debug = config.debug;
60
- if (config.consent !== void 0) legacyConfig.consent = config.consent;
61
- if (config.gdprConsent !== void 0) legacyConfig.gdprConsent = config.gdprConsent;
62
- if (config.autocapture !== void 0) legacyConfig.autocapture = config.autocapture;
63
- if (config.capturePageview !== void 0) legacyConfig.capture_pageview = config.capturePageview;
64
- if (config.capturePageleave !== void 0) legacyConfig.capture_pageleave = config.capturePageleave;
65
- if (config.captureDeadClicks !== void 0) legacyConfig.capture_dead_clicks = config.captureDeadClicks;
66
- if (config.crossSubdomainCookie !== void 0) legacyConfig.cross_subdomain_cookie = config.crossSubdomainCookie;
67
- if (config.disablePersistence !== void 0) legacyConfig.disable_persistence = config.disablePersistence;
68
- if (config.disableSurveys !== void 0) legacyConfig.disable_surveys = config.disableSurveys;
69
- if (config.disableSessionRecording !== void 0) legacyConfig.disable_session_recording = config.disableSessionRecording;
70
- if (config.enableHeatmaps !== void 0) legacyConfig.enable_heatmaps = config.enableHeatmaps;
71
- if (config.maskAllText !== void 0) legacyConfig.mask_all_text = config.maskAllText;
72
- if (config.maskAllElementAttributes !== void 0) {
73
- legacyConfig.mask_all_element_attributes = config.maskAllElementAttributes;
74
- }
75
- if (config.persistence !== void 0) legacyConfig.persistence = config.persistence;
76
- if (config.propertyDenylist !== void 0) legacyConfig.property_denylist = config.propertyDenylist;
77
- if (config.sessionIdleTimeoutSeconds !== void 0) {
78
- legacyConfig.session_idle_timeout_seconds = config.sessionIdleTimeoutSeconds;
79
- }
80
- if (config.beforeSend !== void 0) legacyConfig.before_send = config.beforeSend;
81
- return legacyConfig;
92
+ const payload = { metaData };
93
+ return cleanObject(payload);
82
94
  }
83
95
 
84
96
  // src/core/environment.ts
85
- function isBrowserRuntime() {
86
- return typeof window !== "undefined" && typeof document !== "undefined";
87
- }
88
97
  function getBrowserWindow() {
89
98
  return typeof window === "undefined" ? void 0 : window;
90
99
  }
@@ -144,8 +153,9 @@ function stableStringify(value) {
144
153
  );
145
154
  }
146
155
  function createIdempotencyKey(payload, messageId) {
147
- const event = String(payload.event ?? payload.type ?? "event");
148
- const properties = payload.properties;
156
+ const metaData = payload.metaData;
157
+ const event = String(metaData?.eventType ?? payload.event ?? payload.type ?? "event");
158
+ const properties = metaData ?? payload.properties;
149
159
  const orderId = properties?.orderId ?? properties?.order_id ?? properties?.transaction_id;
150
160
  if (orderId !== void 0) return `${event}:${String(orderId)}`;
151
161
  return `${event}:${stableStringify(properties ?? {}) || messageId}`;
@@ -246,7 +256,17 @@ function createDeliveryManager(config) {
246
256
  persistQueue();
247
257
  }
248
258
  function withEnvelope(payload) {
249
- const messageId = String(payload.messageId ?? createId("msg"));
259
+ const metaData = payload.metaData;
260
+ const messageId = String(metaData?.requestId ?? payload.messageId ?? createId("msg"));
261
+ if (metaData) {
262
+ return {
263
+ ...payload,
264
+ metaData: {
265
+ ...metaData,
266
+ requestId: messageId
267
+ }
268
+ };
269
+ }
250
270
  return {
251
271
  ...payload,
252
272
  messageId,
@@ -272,7 +292,7 @@ function createDeliveryManager(config) {
272
292
  const body = withEnvelope(payload);
273
293
  if (payloadByteLength(body) > maxPayloadBytes) {
274
294
  recordDrop({
275
- messageId: String(body.messageId),
295
+ messageId: String(body.metaData?.requestId ?? body.messageId),
276
296
  reason: "payload_too_large",
277
297
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
278
298
  });
@@ -285,7 +305,7 @@ function createDeliveryManager(config) {
285
305
  const deliveryError = error instanceof Error ? error : new Error(String(error));
286
306
  recordError(deliveryError);
287
307
  enqueue({
288
- messageId: String(body.messageId),
308
+ messageId: String(body.metaData?.requestId ?? body.messageId),
289
309
  savedAt: Date.now(),
290
310
  attempts: 1,
291
311
  lastError: deliveryError.message,
@@ -460,6 +480,12 @@ function endpointFromConfig(config) {
460
480
  const host = config.apiHost ?? "https://sdk.drivemetadata.com/v2";
461
481
  return `${host.replace(/\/$/, "")}/data-collector`;
462
482
  }
483
+ function requireConfigString(value, field) {
484
+ if (typeof value !== "string" || value.trim() === "") {
485
+ throw new Error(`DMD SDK config ${field} is required`);
486
+ }
487
+ return value;
488
+ }
463
489
  function getBrowserStorage() {
464
490
  const browserWindow = getBrowserWindow();
465
491
  try {
@@ -474,6 +500,10 @@ var DriveMetaDataSDK = class {
474
500
  this.queue = [];
475
501
  this.offline = false;
476
502
  this.droppedEvents = 0;
503
+ requireConfigString(config.clientId, "clientId");
504
+ requireConfigString(config.workspaceId, "workspaceId");
505
+ requireConfigString(config.appId, "appId");
506
+ requireConfigString(config.writeKey || config.token, "writeKey or token");
477
507
  this.config = config;
478
508
  this.endpoint = endpointFromConfig(config);
479
509
  const storage = getBrowserStorage();
@@ -497,6 +527,7 @@ var DriveMetaDataSDK = class {
497
527
  this.maxRetryDelayMs = config.delivery?.maxRetryDelayMs ?? 3e4;
498
528
  this.writeKey = config.writeKey || config.token || "";
499
529
  this.identity = { anonymousId: createId2("anon") };
530
+ this.sessionId = createId2("session");
500
531
  this.consentState = normalizeConsent(config.gdprConsent ?? config.consent);
501
532
  this.gdprConsent = this.consentState.analytics;
502
533
  if (!config.delivery?.disableLifecycleFlush) {
@@ -642,7 +673,8 @@ var DriveMetaDataSDK = class {
642
673
  workspaceId: this.config.workspaceId,
643
674
  appId: this.config.appId,
644
675
  writeKey: this.writeKey,
645
- consent: this.consentState
676
+ consent: this.consentState,
677
+ sessionId: this.sessionId
646
678
  };
647
679
  if (this.identity.userId !== void 0) prepared.userId = this.identity.userId;
648
680
  if (this.identity.groupId !== void 0) prepared.groupId = this.identity.groupId;
@@ -666,7 +698,31 @@ var DriveMetaDataSDK = class {
666
698
  if (!validation.ok) {
667
699
  this.lastError = `DMD SDK schema warning: ${validation.errors.join(", ")}`;
668
700
  }
669
- this.sendEvent(prepared);
701
+ this.sendEvent(this.toCollectorPayload(prepared));
702
+ }
703
+ toCollectorPayload(prepared) {
704
+ const browserWindow = getBrowserWindow();
705
+ return createBackendCollectorPayload({
706
+ requestId: prepared.messageId,
707
+ timestamp: prepared.timestamp,
708
+ eventType: prepared.event,
709
+ clientId: prepared.clientId,
710
+ workspaceId: prepared.workspaceId,
711
+ token: prepared.writeKey,
712
+ anonymousId: prepared.anonymousId,
713
+ sessionId: prepared.sessionId,
714
+ ua: browserWindow?.navigator?.userAgent,
715
+ appId: prepared.appId,
716
+ pageUrl: browserWindow?.location?.href,
717
+ eventData: {
718
+ ...prepared.properties,
719
+ anonymousId: prepared.anonymousId,
720
+ sessionId: prepared.sessionId,
721
+ timestamp: prepared.timestamp,
722
+ requestSentAt: prepared.timestamp,
723
+ requestReceivedAt: prepared.timestamp
724
+ }
725
+ });
670
726
  }
671
727
  recordDrop(type, reason, event) {
672
728
  this.droppedEvents += 1;
@@ -680,22 +736,6 @@ var DriveMetaDataSDK = class {
680
736
  }
681
737
  };
682
738
 
683
- // src/browser/legacy-loader.ts
684
- function getLegacySdkInstanceFromWindow() {
685
- const browserWindow = getBrowserWindow();
686
- return browserWindow?.__DriveMetaDataSDKInstance;
687
- }
688
- function ensureLegacySdkLoaded() {
689
- if (!isBrowserRuntime()) {
690
- throw new Error("DMD legacy SDK is only available in a browser runtime");
691
- }
692
- const browserWindow = getBrowserWindow();
693
- if (!browserWindow?.DriveMetaDataSDK) {
694
- throw new Error("DMD legacy SDK constructor is missing from window.DriveMetaDataSDK");
695
- }
696
- return browserWindow.DriveMetaDataSDK;
697
- }
698
-
699
739
  // src/browser/client.ts
700
740
  var singleton;
701
741
  var publicSingleton;
@@ -704,56 +744,34 @@ var lastError;
704
744
  var lastDroppedEvent;
705
745
  function createPublicClient(instance) {
706
746
  return {
707
- __legacy: instance,
708
747
  track(event, properties, options) {
709
- if (instance.trackEvent) {
710
- instance.trackEvent(event, properties, options);
711
- return;
712
- }
713
- instance.sendEvent?.({ eventName: event, event, properties, options });
748
+ instance.trackEvent(event, properties, options);
714
749
  },
715
750
  identify(userId, traits, options) {
716
- if (instance.identify) {
717
- instance.identify(userId, traits, options);
718
- return;
719
- }
720
- instance.identifyUser?.(userId, traits);
751
+ instance.identify(userId, traits, options);
721
752
  },
722
753
  page(name, properties, options) {
723
- if (instance.page) {
724
- instance.page(name, properties, options);
725
- return;
726
- }
727
- instance.trackPageview?.();
754
+ instance.page(name, properties, options);
728
755
  },
729
756
  group(groupId, traits, options) {
730
- instance.group?.(groupId, traits, options);
757
+ instance.group(groupId, traits, options);
731
758
  },
732
759
  alias(previousId, userId, options) {
733
- instance.alias?.(previousId, userId, options);
760
+ instance.alias(previousId, userId, options);
734
761
  },
735
762
  async flush() {
736
- await instance.flush?.();
763
+ await instance.flush();
737
764
  },
738
765
  reset() {
739
- instance.reset?.();
766
+ instance.reset();
740
767
  singleton = void 0;
741
768
  publicSingleton = void 0;
742
769
  },
743
770
  setConsent(consent) {
744
- if (instance.setConsent) {
745
- instance.setConsent(consent);
746
- return;
747
- }
748
- if (typeof consent === "string") {
749
- instance.gdprConsent = consent;
750
- }
771
+ instance.setConsent(consent);
751
772
  },
752
773
  getHealth() {
753
- if (instance.getHealth) {
754
- return instance.getHealth();
755
- }
756
- return getDmdHealth();
774
+ return instance.getHealth();
757
775
  }
758
776
  };
759
777
  }
@@ -778,23 +796,8 @@ function initDmdSDK(config) {
778
796
  if (publicSingleton) {
779
797
  return publicSingleton;
780
798
  }
781
- const legacyConfig = normalizeBrowserConfig(config);
782
- const existingInstance = getLegacySdkInstanceFromWindow();
783
- if (existingInstance) {
784
- return setSingleton(existingInstance);
785
- }
786
799
  try {
787
- let instance;
788
- try {
789
- const LegacySdk = ensureLegacySdkLoaded();
790
- instance = new LegacySdk(legacyConfig);
791
- } catch (error) {
792
- if (error instanceof Error && error.message.includes("constructor is missing")) {
793
- instance = new DriveMetaDataSDK(config);
794
- } else {
795
- throw error;
796
- }
797
- }
800
+ const instance = new DriveMetaDataSDK(config);
798
801
  return setSingleton(instance);
799
802
  } catch (error) {
800
803
  lastError = error instanceof Error ? error.message : String(error);
@@ -861,14 +864,14 @@ function setConsent(consent) {
861
864
  getDmdSDK()?.setConsent(consent);
862
865
  }
863
866
  function getDmdHealth() {
864
- if (singleton?.getHealth) {
867
+ if (singleton) {
865
868
  return singleton.getHealth();
866
869
  }
867
870
  const health = {
868
- initialized: Boolean(singleton?.initialized ?? singleton),
869
- consent: singleton?.gdprConsent ?? "pending",
870
- queueSize: singleton?.queue?.length ?? 0,
871
- offline: Boolean(singleton?.offline),
871
+ initialized: false,
872
+ consent: "pending",
873
+ queueSize: 0,
874
+ offline: false,
872
875
  droppedEvents
873
876
  };
874
877
  if (lastError !== void 0) {