@metamask-previews/analytics-controller 0.0.0-preview-a5935709 → 0.0.0-preview-e493d3e8

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 (55) hide show
  1. package/CHANGELOG.md +1 -1
  2. package/README.md +105 -208
  3. package/dist/AnalyticsController-method-action-types.cjs.map +1 -1
  4. package/dist/AnalyticsController-method-action-types.d.cts +26 -28
  5. package/dist/AnalyticsController-method-action-types.d.cts.map +1 -1
  6. package/dist/AnalyticsController-method-action-types.d.mts +26 -28
  7. package/dist/AnalyticsController-method-action-types.d.mts.map +1 -1
  8. package/dist/AnalyticsController-method-action-types.mjs.map +1 -1
  9. package/dist/AnalyticsController.cjs +73 -110
  10. package/dist/AnalyticsController.cjs.map +1 -1
  11. package/dist/AnalyticsController.d.cts +32 -50
  12. package/dist/AnalyticsController.d.cts.map +1 -1
  13. package/dist/AnalyticsController.d.mts +32 -50
  14. package/dist/AnalyticsController.d.mts.map +1 -1
  15. package/dist/AnalyticsController.mjs +72 -109
  16. package/dist/AnalyticsController.mjs.map +1 -1
  17. package/dist/AnalyticsPlatformAdapter.types.cjs.map +1 -1
  18. package/dist/AnalyticsPlatformAdapter.types.d.cts +15 -63
  19. package/dist/AnalyticsPlatformAdapter.types.d.cts.map +1 -1
  20. package/dist/AnalyticsPlatformAdapter.types.d.mts +15 -63
  21. package/dist/AnalyticsPlatformAdapter.types.d.mts.map +1 -1
  22. package/dist/AnalyticsPlatformAdapter.types.mjs.map +1 -1
  23. package/dist/index.cjs +4 -9
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +4 -5
  26. package/dist/index.d.cts.map +1 -1
  27. package/dist/index.d.mts +4 -5
  28. package/dist/index.d.mts.map +1 -1
  29. package/dist/index.mjs +3 -6
  30. package/dist/index.mjs.map +1 -1
  31. package/package.json +3 -2
  32. package/dist/AnalyticsPlatformAdapterSetupError.cjs +0 -17
  33. package/dist/AnalyticsPlatformAdapterSetupError.cjs.map +0 -1
  34. package/dist/AnalyticsPlatformAdapterSetupError.d.cts +0 -8
  35. package/dist/AnalyticsPlatformAdapterSetupError.d.cts.map +0 -1
  36. package/dist/AnalyticsPlatformAdapterSetupError.d.mts +0 -8
  37. package/dist/AnalyticsPlatformAdapterSetupError.d.mts.map +0 -1
  38. package/dist/AnalyticsPlatformAdapterSetupError.mjs +0 -13
  39. package/dist/AnalyticsPlatformAdapterSetupError.mjs.map +0 -1
  40. package/dist/analyticsControllerStateValidator.cjs +0 -34
  41. package/dist/analyticsControllerStateValidator.cjs.map +0 -1
  42. package/dist/analyticsControllerStateValidator.d.cts +0 -16
  43. package/dist/analyticsControllerStateValidator.d.cts.map +0 -1
  44. package/dist/analyticsControllerStateValidator.d.mts +0 -16
  45. package/dist/analyticsControllerStateValidator.d.mts.map +0 -1
  46. package/dist/analyticsControllerStateValidator.mjs +0 -29
  47. package/dist/analyticsControllerStateValidator.mjs.map +0 -1
  48. package/dist/selectors.cjs +0 -43
  49. package/dist/selectors.cjs.map +0 -1
  50. package/dist/selectors.d.cts +0 -12
  51. package/dist/selectors.d.cts.map +0 -1
  52. package/dist/selectors.d.mts +0 -12
  53. package/dist/selectors.d.mts.map +0 -1
  54. package/dist/selectors.mjs +0 -40
  55. package/dist/selectors.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsController-method-action-types.mjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n */\nexport type AnalyticsControllerTrackViewAction = {\n type: `AnalyticsController:trackView`;\n handler: AnalyticsController['trackView'];\n};\n\n/**\n * Opt in to analytics for regular account.\n * This updates the user's opt-in status for regular account.\n */\nexport type AnalyticsControllerOptInForRegularAccountAction = {\n type: `AnalyticsController:optInForRegularAccount`;\n handler: AnalyticsController['optInForRegularAccount'];\n};\n\n/**\n * Opt out of analytics for regular account.\n * This updates the user's opt-in status for regular account.\n */\nexport type AnalyticsControllerOptOutForRegularAccountAction = {\n type: `AnalyticsController:optOutForRegularAccount`;\n handler: AnalyticsController['optOutForRegularAccount'];\n};\n\n/**\n * Opt in to analytics for social account.\n * This updates the user's opt-in status for social account.\n */\nexport type AnalyticsControllerOptInForSocialAccountAction = {\n type: `AnalyticsController:optInForSocialAccount`;\n handler: AnalyticsController['optInForSocialAccount'];\n};\n\n/**\n * Opt out of analytics for social account.\n * This updates the user's opt-in status for social account.\n */\nexport type AnalyticsControllerOptOutForSocialAccountAction = {\n type: `AnalyticsController:optOutForSocialAccount`;\n handler: AnalyticsController['optOutForSocialAccount'];\n};\n\n/**\n * Union of all AnalyticsController action types.\n */\nexport type AnalyticsControllerMethodActions =\n | AnalyticsControllerTrackEventAction\n | AnalyticsControllerIdentifyAction\n | AnalyticsControllerTrackViewAction\n | AnalyticsControllerOptInForRegularAccountAction\n | AnalyticsControllerOptOutForRegularAccountAction\n | AnalyticsControllerOptInForSocialAccountAction\n | AnalyticsControllerOptOutForSocialAccountAction;\n"]}
1
+ {"version":3,"file":"AnalyticsController-method-action-types.mjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated by `scripts/generate-method-action-types.ts`.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param eventName - The name of the event\n * @param properties - Event properties\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param userId - The user identifier (e.g., metametrics ID)\n * @param traits - User traits/properties\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page view.\n *\n * @param pageName - The name of the page\n * @param properties - Page properties\n */\nexport type AnalyticsControllerTrackPageAction = {\n type: `AnalyticsController:trackPage`;\n handler: AnalyticsController['trackPage'];\n};\n\n/**\n * Enable analytics tracking.\n */\nexport type AnalyticsControllerEnableAction = {\n type: `AnalyticsController:enable`;\n handler: AnalyticsController['enable'];\n};\n\n/**\n * Disable analytics tracking.\n */\nexport type AnalyticsControllerDisableAction = {\n type: `AnalyticsController:disable`;\n handler: AnalyticsController['disable'];\n};\n\n/**\n * Opt in to analytics.\n */\nexport type AnalyticsControllerOptInAction = {\n type: `AnalyticsController:optIn`;\n handler: AnalyticsController['optIn'];\n};\n\n/**\n * Opt out of analytics.\n */\nexport type AnalyticsControllerOptOutAction = {\n type: `AnalyticsController:optOut`;\n handler: AnalyticsController['optOut'];\n};\n\n/**\n * Union of all AnalyticsController action types.\n */\nexport type AnalyticsControllerMethodActions =\n | AnalyticsControllerTrackEventAction\n | AnalyticsControllerIdentifyAction\n | AnalyticsControllerTrackPageAction\n | AnalyticsControllerEnableAction\n | AnalyticsControllerDisableAction\n | AnalyticsControllerOptInAction\n | AnalyticsControllerOptOutAction;\n"]}
@@ -14,9 +14,8 @@ var _AnalyticsController_platformAdapter;
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.AnalyticsController = exports.getDefaultAnalyticsControllerState = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
17
- const analyticsControllerStateValidator_1 = require("./analyticsControllerStateValidator.cjs");
17
+ const uuid_1 = require("uuid");
18
18
  const AnalyticsLogger_1 = require("./AnalyticsLogger.cjs");
19
- const selectors_1 = require("./selectors.cjs");
20
19
  // === GENERAL ===
21
20
  /**
22
21
  * The name of the {@link AnalyticsController}, used to namespace the
@@ -24,56 +23,54 @@ const selectors_1 = require("./selectors.cjs");
24
23
  * when composed with other controllers.
25
24
  */
26
25
  exports.controllerName = 'AnalyticsController';
27
- /**
28
- * Returns default values for AnalyticsController state.
29
- *
30
- * Note: analyticsId is NOT included - it's an identity that must be
31
- * provided by the platform (generated once on first run, then persisted).
32
- *
33
- * @returns Default state without analyticsId
34
- */
35
- function getDefaultAnalyticsControllerState() {
36
- return {
37
- optedInForRegularAccount: false,
38
- optedInForSocialAccount: false,
39
- };
40
- }
41
- exports.getDefaultAnalyticsControllerState = getDefaultAnalyticsControllerState;
42
26
  /**
43
27
  * The metadata for each property in {@link AnalyticsControllerState}.
44
- *
45
- * Note: `persist` is set to `false` for all fields because the platform
46
- * is responsible for persistence via the `stateChange` event listener.
47
28
  */
48
29
  const analyticsControllerMetadata = {
49
- optedInForRegularAccount: {
30
+ enabled: {
50
31
  includeInStateLogs: true,
51
- persist: false,
32
+ persist: true,
52
33
  includeInDebugSnapshot: true,
53
34
  usedInUi: true,
54
35
  },
55
- optedInForSocialAccount: {
36
+ optedIn: {
56
37
  includeInStateLogs: true,
57
- persist: false,
38
+ persist: true,
58
39
  includeInDebugSnapshot: true,
59
40
  usedInUi: true,
60
41
  },
61
42
  analyticsId: {
62
43
  includeInStateLogs: true,
63
- persist: false,
44
+ persist: true,
64
45
  includeInDebugSnapshot: true,
65
46
  usedInUi: false,
66
47
  },
67
48
  };
49
+ /**
50
+ * Constructs the default {@link AnalyticsController} state. This allows
51
+ * consumers to provide a partial state object when initializing the controller
52
+ * and also helps in constructing complete state objects for this controller in
53
+ * tests.
54
+ *
55
+ * @returns The default {@link AnalyticsController} state.
56
+ */
57
+ function getDefaultAnalyticsControllerState() {
58
+ return {
59
+ enabled: true,
60
+ optedIn: false,
61
+ analyticsId: (0, uuid_1.v4)(),
62
+ };
63
+ }
64
+ exports.getDefaultAnalyticsControllerState = getDefaultAnalyticsControllerState;
68
65
  // === MESSENGER ===
69
66
  const MESSENGER_EXPOSED_METHODS = [
70
67
  'trackEvent',
71
68
  'identify',
72
- 'trackView',
73
- 'optInForRegularAccount',
74
- 'optOutForRegularAccount',
75
- 'optInForSocialAccount',
76
- 'optOutForSocialAccount',
69
+ 'trackPage',
70
+ 'enable',
71
+ 'disable',
72
+ 'optIn',
73
+ 'optOut',
77
74
  ];
78
75
  /**
79
76
  * The AnalyticsController manages analytics tracking across platforms (Mobile/Extension).
@@ -84,149 +81,115 @@ const MESSENGER_EXPOSED_METHODS = [
84
81
  * This controller follows the MetaMask controller pattern and integrates with the
85
82
  * messenger system to allow other controllers and components to track analytics events.
86
83
  * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.
87
- *
88
- * Note: This controller does not persist state internally (`persist: false` in metadata).
89
- * The platform is responsible for:
90
- * - Providing the initial state (including a valid UUIDv4 analyticsId)
91
- * - Subscribing to `AnalyticsController:stateChange` event to persist changes
92
84
  */
93
85
  class AnalyticsController extends base_controller_1.BaseController {
94
86
  /**
95
87
  * Constructs an AnalyticsController instance.
96
88
  *
97
89
  * @param options - Controller options
98
- * @param options.state - Initial controller state. Must include a valid UUIDv4 `analyticsId`.
99
- * Use `getDefaultAnalyticsControllerState()` for default opt-in preferences.
90
+ * @param options.state - Initial controller state (defaults from getDefaultAnalyticsControllerState)
100
91
  * @param options.messenger - Messenger used to communicate with BaseController
101
92
  * @param options.platformAdapter - Platform adapter implementation for tracking
102
- * @throws Error if state.analyticsId is missing or not a valid UUIDv4
103
93
  */
104
- constructor({ state, messenger, platformAdapter, }) {
105
- const initialState = {
106
- ...getDefaultAnalyticsControllerState(),
107
- ...state,
108
- };
109
- (0, analyticsControllerStateValidator_1.validateAnalyticsControllerState)(initialState);
94
+ constructor({ state = {}, messenger, platformAdapter, }) {
110
95
  super({
111
96
  name: exports.controllerName,
112
97
  metadata: analyticsControllerMetadata,
113
- state: initialState,
98
+ state: {
99
+ ...getDefaultAnalyticsControllerState(),
100
+ ...state,
101
+ },
114
102
  messenger,
115
103
  });
116
104
  _AnalyticsController_platformAdapter.set(this, void 0);
117
105
  __classPrivateFieldSet(this, _AnalyticsController_platformAdapter, platformAdapter, "f");
118
106
  this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
119
107
  (0, AnalyticsLogger_1.projectLogger)('AnalyticsController initialized and ready', {
120
- enabled: selectors_1.analyticsControllerSelectors.selectEnabled(this.state),
121
- optedIn: this.state.optedInForRegularAccount,
122
- socialOptedIn: this.state.optedInForSocialAccount,
108
+ enabled: this.state.enabled,
109
+ optedIn: this.state.optedIn,
123
110
  analyticsId: this.state.analyticsId,
124
111
  });
125
- // Call onSetupCompleted lifecycle hook after initialization
126
- // State is already validated, so analyticsId is guaranteed to be a valid UUIDv4
127
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f")
128
- .onSetupCompleted(this.state.analyticsId)
129
- .catch((error) => {
130
- // Log error but don't throw - adapter setup failure shouldn't break controller
131
- (0, AnalyticsLogger_1.projectLogger)('Error calling platformAdapter.onSetupCompleted', error);
132
- });
133
112
  }
134
113
  /**
135
114
  * Track an analytics event.
136
115
  *
137
116
  * Events are only tracked if analytics is enabled.
138
117
  *
139
- * @param event - Analytics event with properties and sensitive properties
118
+ * @param eventName - The name of the event
119
+ * @param properties - Event properties
140
120
  */
141
- trackEvent(event) {
121
+ trackEvent(eventName, properties = {}) {
142
122
  // Don't track if analytics is disabled
143
- if (!selectors_1.analyticsControllerSelectors.selectEnabled(this.state)) {
144
- return;
145
- }
146
- // Derive sensitivity from presence of sensitiveProperties
147
- const hasSensitiveProperties = Object.keys(event.sensitiveProperties).length > 0;
148
- // if event does not have properties, send event without properties
149
- // and return to prevent any additional processing
150
- if (!event.hasProperties) {
151
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").track(event.name);
123
+ if (!this.state.enabled) {
152
124
  return;
153
125
  }
154
- // Track regular properties (without isSensitive flag - it's the default)
155
- // Note: Even if properties object is empty, we still send it to ensure
156
- // an event with user ID is tracked. When only sensitiveProperties exist,
157
- // this creates two events: one with empty props (user ID) and one with
158
- // sensitive props (anonymous ID), which is the expected behavior.
159
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").track(event.name, {
160
- ...event.properties,
161
- });
162
- // Track sensitive properties in a separate event with isSensitive flag
163
- if (hasSensitiveProperties) {
164
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").track(event.name, {
165
- ...event.properties,
166
- ...event.sensitiveProperties,
167
- isSensitive: true,
168
- });
169
- }
126
+ // Delegate to platform adapter
127
+ __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").trackEvent(eventName, properties);
170
128
  }
171
129
  /**
172
130
  * Identify a user for analytics.
173
131
  *
132
+ * @param userId - The user identifier (e.g., metametrics ID)
174
133
  * @param traits - User traits/properties
175
134
  */
176
- identify(traits) {
177
- if (!selectors_1.analyticsControllerSelectors.selectEnabled(this.state)) {
135
+ identify(userId, traits) {
136
+ if (!this.state.enabled) {
178
137
  return;
179
138
  }
180
- // Delegate to platform adapter using the current analytics ID
181
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").identify(this.state.analyticsId, traits);
139
+ // Update state with analytics ID
140
+ this.update((state) => {
141
+ state.analyticsId = userId;
142
+ });
143
+ // Delegate to platform adapter if supported
144
+ if (__classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").identify) {
145
+ __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").identify(userId, traits);
146
+ }
182
147
  }
183
148
  /**
184
- * Track a page or screen view.
149
+ * Track a page view.
185
150
  *
186
- * @param name - The identifier/name of the page or screen being viewed (e.g., "home", "settings", "wallet")
187
- * @param properties - Optional properties associated with the view
151
+ * @param pageName - The name of the page
152
+ * @param properties - Page properties
188
153
  */
189
- trackView(name, properties) {
190
- if (!selectors_1.analyticsControllerSelectors.selectEnabled(this.state)) {
154
+ trackPage(pageName, properties) {
155
+ if (!this.state.enabled) {
191
156
  return;
192
157
  }
193
- // Delegate to platform adapter
194
- __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").view(name, properties);
158
+ // Delegate to platform adapter if supported
159
+ if (__classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").trackPage) {
160
+ __classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").trackPage(pageName, properties);
161
+ }
195
162
  }
196
163
  /**
197
- * Opt in to analytics for regular account.
198
- * This updates the user's opt-in status for regular account.
164
+ * Enable analytics tracking.
199
165
  */
200
- optInForRegularAccount() {
166
+ enable() {
201
167
  this.update((state) => {
202
- state.optedInForRegularAccount = true;
168
+ state.enabled = true;
203
169
  });
204
170
  }
205
171
  /**
206
- * Opt out of analytics for regular account.
207
- * This updates the user's opt-in status for regular account.
172
+ * Disable analytics tracking.
208
173
  */
209
- optOutForRegularAccount() {
174
+ disable() {
210
175
  this.update((state) => {
211
- state.optedInForRegularAccount = false;
176
+ state.enabled = false;
212
177
  });
213
178
  }
214
179
  /**
215
- * Opt in to analytics for social account.
216
- * This updates the user's opt-in status for social account.
180
+ * Opt in to analytics.
217
181
  */
218
- optInForSocialAccount() {
182
+ optIn() {
219
183
  this.update((state) => {
220
- state.optedInForSocialAccount = true;
184
+ state.optedIn = true;
221
185
  });
222
186
  }
223
187
  /**
224
- * Opt out of analytics for social account.
225
- * This updates the user's opt-in status for social account.
188
+ * Opt out of analytics.
226
189
  */
227
- optOutForSocialAccount() {
190
+ optOut() {
228
191
  this.update((state) => {
229
- state.optedInForSocialAccount = false;
192
+ state.optedIn = false;
230
193
  });
231
194
  }
232
195
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsController.cjs","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\n\nimport type { AnalyticsControllerMethodActions } from './AnalyticsController-method-action-types';\nimport { validateAnalyticsControllerState } from './analyticsControllerStateValidator';\nimport { projectLogger } from './AnalyticsLogger';\nimport type {\n AnalyticsPlatformAdapter,\n AnalyticsEventProperties,\n AnalyticsUserTraits,\n AnalyticsTrackingEvent,\n} from './AnalyticsPlatformAdapter.types';\nimport { analyticsControllerSelectors } from './selectors';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link AnalyticsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'AnalyticsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link AnalyticsController}.\n */\nexport type AnalyticsControllerState = {\n /**\n * Whether the user has opted in to analytics for regular account.\n */\n optedInForRegularAccount: boolean;\n\n /**\n * Whether the user has opted in to analytics for social account.\n */\n optedInForSocialAccount: boolean;\n\n /**\n * User's UUIDv4 analytics identifier.\n * This is an identity (unique per user), not a preference.\n * Must be provided by the platform - the controller does not generate it.\n */\n analyticsId: string;\n};\n\n/**\n * Returns default values for AnalyticsController state.\n *\n * Note: analyticsId is NOT included - it's an identity that must be\n * provided by the platform (generated once on first run, then persisted).\n *\n * @returns Default state without analyticsId\n */\nexport function getDefaultAnalyticsControllerState(): Omit<\n AnalyticsControllerState,\n 'analyticsId'\n> {\n return {\n optedInForRegularAccount: false,\n optedInForSocialAccount: false,\n };\n}\n\n/**\n * The metadata for each property in {@link AnalyticsControllerState}.\n *\n * Note: `persist` is set to `false` for all fields because the platform\n * is responsible for persistence via the `stateChange` event listener.\n */\nconst analyticsControllerMetadata = {\n optedInForRegularAccount: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n optedInForSocialAccount: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n analyticsId: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<AnalyticsControllerState>;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'trackEvent',\n 'identify',\n 'trackView',\n 'optInForRegularAccount',\n 'optOutForRegularAccount',\n 'optInForSocialAccount',\n 'optOutForSocialAccount',\n] as const;\n\n/**\n * Returns the state of the {@link AnalyticsController}.\n */\nexport type AnalyticsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Actions that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerActions =\n | AnalyticsControllerGetStateAction\n | AnalyticsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link AnalyticsControllerMessenger} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Event emitted when the state of the {@link AnalyticsController} changes.\n */\nexport type AnalyticsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Events that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerEvents = AnalyticsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link AnalyticsControllerMessenger} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link AnalyticsController}.\n */\nexport type AnalyticsControllerMessenger = Messenger<\n typeof controllerName,\n AnalyticsControllerActions | AllowedActions,\n AnalyticsControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options that AnalyticsController takes.\n */\nexport type AnalyticsControllerOptions = {\n /**\n * Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * The platform is responsible for generating and persisting the analyticsId.\n */\n state: AnalyticsControllerState;\n /**\n * Messenger used to communicate with BaseController and other controllers.\n */\n messenger: AnalyticsControllerMessenger;\n /**\n * Platform adapter implementation for tracking events.\n */\n platformAdapter: AnalyticsPlatformAdapter;\n};\n\n/**\n * The AnalyticsController manages analytics tracking across platforms (Mobile/Extension).\n * It provides a unified interface for tracking events, identifying users, and managing\n * analytics preferences while delegating platform-specific implementation to an\n * {@link AnalyticsPlatformAdapter}.\n *\n * This controller follows the MetaMask controller pattern and integrates with the\n * messenger system to allow other controllers and components to track analytics events.\n * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.\n *\n * Note: This controller does not persist state internally (`persist: false` in metadata).\n * The platform is responsible for:\n * - Providing the initial state (including a valid UUIDv4 analyticsId)\n * - Subscribing to `AnalyticsController:stateChange` event to persist changes\n */\nexport class AnalyticsController extends BaseController<\n 'AnalyticsController',\n AnalyticsControllerState,\n AnalyticsControllerMessenger\n> {\n readonly #platformAdapter: AnalyticsPlatformAdapter;\n\n /**\n * Constructs an AnalyticsController instance.\n *\n * @param options - Controller options\n * @param options.state - Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * Use `getDefaultAnalyticsControllerState()` for default opt-in preferences.\n * @param options.messenger - Messenger used to communicate with BaseController\n * @param options.platformAdapter - Platform adapter implementation for tracking\n * @throws Error if state.analyticsId is missing or not a valid UUIDv4\n */\n constructor({\n state,\n messenger,\n platformAdapter,\n }: AnalyticsControllerOptions) {\n const initialState: AnalyticsControllerState = {\n ...getDefaultAnalyticsControllerState(),\n ...state,\n };\n\n validateAnalyticsControllerState(initialState);\n\n super({\n name: controllerName,\n metadata: analyticsControllerMetadata,\n state: initialState,\n messenger,\n });\n\n this.#platformAdapter = platformAdapter;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n projectLogger('AnalyticsController initialized and ready', {\n enabled: analyticsControllerSelectors.selectEnabled(this.state),\n optedIn: this.state.optedInForRegularAccount,\n socialOptedIn: this.state.optedInForSocialAccount,\n analyticsId: this.state.analyticsId,\n });\n\n // Call onSetupCompleted lifecycle hook after initialization\n // State is already validated, so analyticsId is guaranteed to be a valid UUIDv4\n this.#platformAdapter\n .onSetupCompleted(this.state.analyticsId)\n .catch((error) => {\n // Log error but don't throw - adapter setup failure shouldn't break controller\n projectLogger('Error calling platformAdapter.onSetupCompleted', error);\n });\n }\n\n /**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n */\n trackEvent(event: AnalyticsTrackingEvent): void {\n // Don't track if analytics is disabled\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Derive sensitivity from presence of sensitiveProperties\n const hasSensitiveProperties =\n Object.keys(event.sensitiveProperties).length > 0;\n\n // if event does not have properties, send event without properties\n // and return to prevent any additional processing\n if (!event.hasProperties) {\n this.#platformAdapter.track(event.name);\n return;\n }\n\n // Track regular properties (without isSensitive flag - it's the default)\n // Note: Even if properties object is empty, we still send it to ensure\n // an event with user ID is tracked. When only sensitiveProperties exist,\n // this creates two events: one with empty props (user ID) and one with\n // sensitive props (anonymous ID), which is the expected behavior.\n this.#platformAdapter.track(event.name, {\n ...event.properties,\n });\n\n // Track sensitive properties in a separate event with isSensitive flag\n if (hasSensitiveProperties) {\n this.#platformAdapter.track(event.name, {\n ...event.properties,\n ...event.sensitiveProperties,\n isSensitive: true,\n });\n }\n }\n\n /**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n */\n identify(traits?: AnalyticsUserTraits): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter using the current analytics ID\n this.#platformAdapter.identify(this.state.analyticsId, traits);\n }\n\n /**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n */\n trackView(name: string, properties?: AnalyticsEventProperties): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter\n this.#platformAdapter.view(name, properties);\n }\n\n /**\n * Opt in to analytics for regular account.\n * This updates the user's opt-in status for regular account.\n */\n optInForRegularAccount(): void {\n this.update((state) => {\n state.optedInForRegularAccount = true;\n });\n }\n\n /**\n * Opt out of analytics for regular account.\n * This updates the user's opt-in status for regular account.\n */\n optOutForRegularAccount(): void {\n this.update((state) => {\n state.optedInForRegularAccount = false;\n });\n }\n\n /**\n * Opt in to analytics for social account.\n * This updates the user's opt-in status for social account.\n */\n optInForSocialAccount(): void {\n this.update((state) => {\n state.optedInForSocialAccount = true;\n });\n }\n\n /**\n * Opt out of analytics for social account.\n * This updates the user's opt-in status for social account.\n */\n optOutForSocialAccount(): void {\n this.update((state) => {\n state.optedInForSocialAccount = false;\n });\n }\n}\n"]}
1
+ {"version":3,"file":"AnalyticsController.cjs","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport type { AnalyticsControllerMethodActions } from './AnalyticsController-method-action-types';\nimport { projectLogger } from './AnalyticsLogger';\nimport type {\n AnalyticsPlatformAdapter,\n AnalyticsEventProperties,\n} from './AnalyticsPlatformAdapter.types';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link AnalyticsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'AnalyticsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link AnalyticsController}.\n */\nexport type AnalyticsControllerState = {\n /**\n * Whether analytics tracking is enabled\n */\n enabled: boolean;\n\n /**\n * Whether the user has opted in to analytics\n */\n optedIn: boolean;\n\n /**\n * User's UUIDv4 analytics identifier\n */\n analyticsId: string;\n};\n\n/**\n * The metadata for each property in {@link AnalyticsControllerState}.\n */\nconst analyticsControllerMetadata = {\n enabled: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n optedIn: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n analyticsId: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n} satisfies StateMetadata<AnalyticsControllerState>;\n\n/**\n * Constructs the default {@link AnalyticsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link AnalyticsController} state.\n */\nexport function getDefaultAnalyticsControllerState(): AnalyticsControllerState {\n return {\n enabled: true,\n optedIn: false,\n analyticsId: uuidv4(),\n };\n}\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'trackEvent',\n 'identify',\n 'trackPage',\n 'enable',\n 'disable',\n 'optIn',\n 'optOut',\n] as const;\n\n/**\n * Returns the state of the {@link AnalyticsController}.\n */\nexport type AnalyticsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Actions that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerActions =\n | AnalyticsControllerGetStateAction\n | AnalyticsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link AnalyticsControllerMessenger} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Event emitted when the state of the {@link AnalyticsController} changes.\n */\nexport type AnalyticsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Events that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerEvents = AnalyticsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link AnalyticsControllerMessenger} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link AnalyticsController}.\n */\nexport type AnalyticsControllerMessenger = Messenger<\n typeof controllerName,\n AnalyticsControllerActions | AllowedActions,\n AnalyticsControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options that AnalyticsController takes.\n */\nexport type AnalyticsControllerOptions = {\n state?: Partial<AnalyticsControllerState>;\n messenger: AnalyticsControllerMessenger;\n /**\n * Platform adapter implementation for tracking events\n */\n platformAdapter: AnalyticsPlatformAdapter;\n};\n\n/**\n * The AnalyticsController manages analytics tracking across platforms (Mobile/Extension).\n * It provides a unified interface for tracking events, identifying users, and managing\n * analytics preferences while delegating platform-specific implementation to an\n * {@link AnalyticsPlatformAdapter}.\n *\n * This controller follows the MetaMask controller pattern and integrates with the\n * messenger system to allow other controllers and components to track analytics events.\n * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.\n */\nexport class AnalyticsController extends BaseController<\n 'AnalyticsController',\n AnalyticsControllerState,\n AnalyticsControllerMessenger\n> {\n readonly #platformAdapter: AnalyticsPlatformAdapter;\n\n /**\n * Constructs an AnalyticsController instance.\n *\n * @param options - Controller options\n * @param options.state - Initial controller state (defaults from getDefaultAnalyticsControllerState)\n * @param options.messenger - Messenger used to communicate with BaseController\n * @param options.platformAdapter - Platform adapter implementation for tracking\n */\n constructor({\n state = {},\n messenger,\n platformAdapter,\n }: AnalyticsControllerOptions) {\n super({\n name: controllerName,\n metadata: analyticsControllerMetadata,\n state: {\n ...getDefaultAnalyticsControllerState(),\n ...state,\n },\n messenger,\n });\n\n this.#platformAdapter = platformAdapter;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n projectLogger('AnalyticsController initialized and ready', {\n enabled: this.state.enabled,\n optedIn: this.state.optedIn,\n analyticsId: this.state.analyticsId,\n });\n }\n\n /**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param eventName - The name of the event\n * @param properties - Event properties\n */\n trackEvent(\n eventName: string,\n properties: AnalyticsEventProperties = {},\n ): void {\n // Don't track if analytics is disabled\n if (!this.state.enabled) {\n return;\n }\n\n // Delegate to platform adapter\n this.#platformAdapter.trackEvent(eventName, properties);\n }\n\n /**\n * Identify a user for analytics.\n *\n * @param userId - The user identifier (e.g., metametrics ID)\n * @param traits - User traits/properties\n */\n identify(userId: string, traits?: AnalyticsEventProperties): void {\n if (!this.state.enabled) {\n return;\n }\n\n // Update state with analytics ID\n this.update((state) => {\n state.analyticsId = userId;\n });\n\n // Delegate to platform adapter if supported\n if (this.#platformAdapter.identify) {\n this.#platformAdapter.identify(userId, traits);\n }\n }\n\n /**\n * Track a page view.\n *\n * @param pageName - The name of the page\n * @param properties - Page properties\n */\n trackPage(pageName: string, properties?: AnalyticsEventProperties): void {\n if (!this.state.enabled) {\n return;\n }\n\n // Delegate to platform adapter if supported\n if (this.#platformAdapter.trackPage) {\n this.#platformAdapter.trackPage(pageName, properties);\n }\n }\n\n /**\n * Enable analytics tracking.\n */\n enable(): void {\n this.update((state) => {\n state.enabled = true;\n });\n }\n\n /**\n * Disable analytics tracking.\n */\n disable(): void {\n this.update((state) => {\n state.enabled = false;\n });\n }\n\n /**\n * Opt in to analytics.\n */\n optIn(): void {\n this.update((state) => {\n state.optedIn = true;\n });\n }\n\n /**\n * Opt out of analytics.\n */\n optOut(): void {\n this.update((state) => {\n state.optedIn = false;\n });\n }\n}\n"]}
@@ -2,7 +2,7 @@ import type { ControllerGetStateAction, ControllerStateChangeEvent } from "@meta
2
2
  import { BaseController } from "@metamask/base-controller";
3
3
  import type { Messenger } from "@metamask/messenger";
4
4
  import type { AnalyticsControllerMethodActions } from "./AnalyticsController-method-action-types.cjs";
5
- import type { AnalyticsPlatformAdapter, AnalyticsEventProperties, AnalyticsUserTraits, AnalyticsTrackingEvent } from "./AnalyticsPlatformAdapter.types.cjs";
5
+ import type { AnalyticsPlatformAdapter, AnalyticsEventProperties } from "./AnalyticsPlatformAdapter.types.cjs";
6
6
  /**
7
7
  * The name of the {@link AnalyticsController}, used to namespace the
8
8
  * controller's actions and events and to namespace the controller's state data
@@ -14,29 +14,27 @@ export declare const controllerName = "AnalyticsController";
14
14
  */
15
15
  export type AnalyticsControllerState = {
16
16
  /**
17
- * Whether the user has opted in to analytics for regular account.
17
+ * Whether analytics tracking is enabled
18
18
  */
19
- optedInForRegularAccount: boolean;
19
+ enabled: boolean;
20
20
  /**
21
- * Whether the user has opted in to analytics for social account.
21
+ * Whether the user has opted in to analytics
22
22
  */
23
- optedInForSocialAccount: boolean;
23
+ optedIn: boolean;
24
24
  /**
25
- * User's UUIDv4 analytics identifier.
26
- * This is an identity (unique per user), not a preference.
27
- * Must be provided by the platform - the controller does not generate it.
25
+ * User's UUIDv4 analytics identifier
28
26
  */
29
27
  analyticsId: string;
30
28
  };
31
29
  /**
32
- * Returns default values for AnalyticsController state.
30
+ * Constructs the default {@link AnalyticsController} state. This allows
31
+ * consumers to provide a partial state object when initializing the controller
32
+ * and also helps in constructing complete state objects for this controller in
33
+ * tests.
33
34
  *
34
- * Note: analyticsId is NOT included - it's an identity that must be
35
- * provided by the platform (generated once on first run, then persisted).
36
- *
37
- * @returns Default state without analyticsId
35
+ * @returns The default {@link AnalyticsController} state.
38
36
  */
39
- export declare function getDefaultAnalyticsControllerState(): Omit<AnalyticsControllerState, 'analyticsId'>;
37
+ export declare function getDefaultAnalyticsControllerState(): AnalyticsControllerState;
40
38
  /**
41
39
  * Returns the state of the {@link AnalyticsController}.
42
40
  */
@@ -70,17 +68,10 @@ export type AnalyticsControllerMessenger = Messenger<typeof controllerName, Anal
70
68
  * The options that AnalyticsController takes.
71
69
  */
72
70
  export type AnalyticsControllerOptions = {
73
- /**
74
- * Initial controller state. Must include a valid UUIDv4 `analyticsId`.
75
- * The platform is responsible for generating and persisting the analyticsId.
76
- */
77
- state: AnalyticsControllerState;
78
- /**
79
- * Messenger used to communicate with BaseController and other controllers.
80
- */
71
+ state?: Partial<AnalyticsControllerState>;
81
72
  messenger: AnalyticsControllerMessenger;
82
73
  /**
83
- * Platform adapter implementation for tracking events.
74
+ * Platform adapter implementation for tracking events
84
75
  */
85
76
  platformAdapter: AnalyticsPlatformAdapter;
86
77
  };
@@ -93,11 +84,6 @@ export type AnalyticsControllerOptions = {
93
84
  * This controller follows the MetaMask controller pattern and integrates with the
94
85
  * messenger system to allow other controllers and components to track analytics events.
95
86
  * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.
96
- *
97
- * Note: This controller does not persist state internally (`persist: false` in metadata).
98
- * The platform is responsible for:
99
- * - Providing the initial state (including a valid UUIDv4 analyticsId)
100
- * - Subscribing to `AnalyticsController:stateChange` event to persist changes
101
87
  */
102
88
  export declare class AnalyticsController extends BaseController<'AnalyticsController', AnalyticsControllerState, AnalyticsControllerMessenger> {
103
89
  #private;
@@ -105,11 +91,9 @@ export declare class AnalyticsController extends BaseController<'AnalyticsContro
105
91
  * Constructs an AnalyticsController instance.
106
92
  *
107
93
  * @param options - Controller options
108
- * @param options.state - Initial controller state. Must include a valid UUIDv4 `analyticsId`.
109
- * Use `getDefaultAnalyticsControllerState()` for default opt-in preferences.
94
+ * @param options.state - Initial controller state (defaults from getDefaultAnalyticsControllerState)
110
95
  * @param options.messenger - Messenger used to communicate with BaseController
111
96
  * @param options.platformAdapter - Platform adapter implementation for tracking
112
- * @throws Error if state.analyticsId is missing or not a valid UUIDv4
113
97
  */
114
98
  constructor({ state, messenger, platformAdapter, }: AnalyticsControllerOptions);
115
99
  /**
@@ -117,42 +101,40 @@ export declare class AnalyticsController extends BaseController<'AnalyticsContro
117
101
  *
118
102
  * Events are only tracked if analytics is enabled.
119
103
  *
120
- * @param event - Analytics event with properties and sensitive properties
104
+ * @param eventName - The name of the event
105
+ * @param properties - Event properties
121
106
  */
122
- trackEvent(event: AnalyticsTrackingEvent): void;
107
+ trackEvent(eventName: string, properties?: AnalyticsEventProperties): void;
123
108
  /**
124
109
  * Identify a user for analytics.
125
110
  *
111
+ * @param userId - The user identifier (e.g., metametrics ID)
126
112
  * @param traits - User traits/properties
127
113
  */
128
- identify(traits?: AnalyticsUserTraits): void;
114
+ identify(userId: string, traits?: AnalyticsEventProperties): void;
129
115
  /**
130
- * Track a page or screen view.
116
+ * Track a page view.
131
117
  *
132
- * @param name - The identifier/name of the page or screen being viewed (e.g., "home", "settings", "wallet")
133
- * @param properties - Optional properties associated with the view
118
+ * @param pageName - The name of the page
119
+ * @param properties - Page properties
134
120
  */
135
- trackView(name: string, properties?: AnalyticsEventProperties): void;
121
+ trackPage(pageName: string, properties?: AnalyticsEventProperties): void;
136
122
  /**
137
- * Opt in to analytics for regular account.
138
- * This updates the user's opt-in status for regular account.
123
+ * Enable analytics tracking.
139
124
  */
140
- optInForRegularAccount(): void;
125
+ enable(): void;
141
126
  /**
142
- * Opt out of analytics for regular account.
143
- * This updates the user's opt-in status for regular account.
127
+ * Disable analytics tracking.
144
128
  */
145
- optOutForRegularAccount(): void;
129
+ disable(): void;
146
130
  /**
147
- * Opt in to analytics for social account.
148
- * This updates the user's opt-in status for social account.
131
+ * Opt in to analytics.
149
132
  */
150
- optInForSocialAccount(): void;
133
+ optIn(): void;
151
134
  /**
152
- * Opt out of analytics for social account.
153
- * This updates the user's opt-in status for social account.
135
+ * Opt out of analytics.
154
136
  */
155
- optOutForSocialAccount(): void;
137
+ optOut(): void;
156
138
  }
157
139
  export {};
158
140
  //# sourceMappingURL=AnalyticsController.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnalyticsController.d.cts","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAErD,OAAO,KAAK,EAAE,gCAAgC,EAAE,sDAAkD;AAGlG,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACvB,6CAAyC;AAK1C;;;;GAIG;AACH,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAIpD;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,wBAAwB,EAAE,OAAO,CAAC;IAElC;;OAEG;IACH,uBAAuB,EAAE,OAAO,CAAC;IAEjC;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,IAAI,IAAI,CACxD,wBAAwB,EACxB,aAAa,CACd,CAKA;AAyCD;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG,wBAAwB,CACtE,OAAO,cAAc,EACrB,wBAAwB,CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAClC,iCAAiC,GACjC,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAAG,0BAA0B,CAC1E,OAAO,cAAc,EACrB,wBAAwB,CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,mCAAmC,CAAC;AAE5E;;GAEG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GAAG,SAAS,CAClD,OAAO,cAAc,EACrB,0BAA0B,GAAG,cAAc,EAC3C,yBAAyB,GAAG,aAAa,CAC1C,CAAC;AAIF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC;;;OAGG;IACH,KAAK,EAAE,wBAAwB,CAAC;IAChC;;OAEG;IACH,SAAS,EAAE,4BAA4B,CAAC;IACxC;;OAEG;IACH,eAAe,EAAE,wBAAwB,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,qBAAa,mBAAoB,SAAQ,cAAc,CACrD,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,CAC7B;;IAGC;;;;;;;;;OASG;gBACS,EACV,KAAK,EACL,SAAS,EACT,eAAe,GAChB,EAAE,0BAA0B;IAuC7B;;;;;;OAMG;IACH,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,IAAI;IAoC/C;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,GAAG,IAAI;IAS5C;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,wBAAwB,GAAG,IAAI;IASpE;;;OAGG;IACH,sBAAsB,IAAI,IAAI;IAM9B;;;OAGG;IACH,uBAAuB,IAAI,IAAI;IAM/B;;;OAGG;IACH,qBAAqB,IAAI,IAAI;IAM7B;;;OAGG;IACH,sBAAsB,IAAI,IAAI;CAK/B"}
1
+ {"version":3,"file":"AnalyticsController.d.cts","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AAGrD,OAAO,KAAK,EAAE,gCAAgC,EAAE,sDAAkD;AAElG,OAAO,KAAK,EACV,wBAAwB,EACxB,wBAAwB,EACzB,6CAAyC;AAI1C;;;;GAIG;AACH,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAIpD;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AA0BF;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,IAAI,wBAAwB,CAM7E;AAcD;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG,wBAAwB,CACtE,OAAO,cAAc,EACrB,wBAAwB,CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAClC,iCAAiC,GACjC,gCAAgC,CAAC;AAErC;;GAEG;AACH,KAAK,cAAc,GAAG,KAAK,CAAC;AAE5B;;GAEG;AACH,MAAM,MAAM,mCAAmC,GAAG,0BAA0B,CAC1E,OAAO,cAAc,EACrB,wBAAwB,CACzB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,mCAAmC,CAAC;AAE5E;;GAEG;AACH,KAAK,aAAa,GAAG,KAAK,CAAC;AAE3B;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GAAG,SAAS,CAClD,OAAO,cAAc,EACrB,0BAA0B,GAAG,cAAc,EAC3C,yBAAyB,GAAG,aAAa,CAC1C,CAAC;AAIF;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,KAAK,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC1C,SAAS,EAAE,4BAA4B,CAAC;IACxC;;OAEG;IACH,eAAe,EAAE,wBAAwB,CAAC;CAC3C,CAAC;AAEF;;;;;;;;;GASG;AACH,qBAAa,mBAAoB,SAAQ,cAAc,CACrD,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,CAC7B;;IAGC;;;;;;;OAOG;gBACS,EACV,KAAU,EACV,SAAS,EACT,eAAe,GAChB,EAAE,0BAA0B;IAyB7B;;;;;;;OAOG;IACH,UAAU,CACR,SAAS,EAAE,MAAM,EACjB,UAAU,GAAE,wBAA6B,GACxC,IAAI;IAUP;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,wBAAwB,GAAG,IAAI;IAgBjE;;;;;OAKG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,wBAAwB,GAAG,IAAI;IAWxE;;OAEG;IACH,MAAM,IAAI,IAAI;IAMd;;OAEG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;IACH,KAAK,IAAI,IAAI;IAMb;;OAEG;IACH,MAAM,IAAI,IAAI;CAKf"}