clarity-analytics-sdk 1.0.5 → 1.0.7

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +61 -28
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clarity-analytics-sdk",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "A lightweight JavaScript SDK for tracking events and analytics with Clarity Analytics",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -20,11 +20,9 @@
20
20
  apiUrl: 'https://apps.helo.ai/api/v1/sdk/clarity/events/publish-event',
21
21
  fetchUserIdUrl: 'https://apps.helo.ai/api/v1/sdk/clarity/projects?id=',
22
22
  projectId: config.projectId,
23
- projectName: config.projectName || '',
24
- apiKey: config.apiKey || null,
25
- userId: null, // Will be fetched from backend
26
- systemUserId: null, // Will be fetched from backend API
27
- sessionId: config.sessionId || this._generateSessionId(),
23
+ projectName: null,
24
+ userId: null, // customer: should come from app
25
+ systemUserId: null, // Will be fetched from backend API(user who logged in clarity)
28
26
  debug: config.debug || false,
29
27
  retryAttempts: config.retryAttempts || 3,
30
28
  timeout: config.timeout || 10000,
@@ -50,15 +48,20 @@
50
48
  async _initialize (config) {
51
49
  try {
52
50
  // Fetch user ID from backend
53
- const { userId, ipaddress } = await this._fetchUserId(this.config.projectId)
54
-
55
- if (!userId) {
51
+ const { systemUserId, ipaddress, projectName } = await this._fetchUserId(this.config.projectId)
52
+ if (!systemUserId) {
56
53
  throw new Error('Failed to fetch user ID from backend')
57
54
  }
58
55
 
59
- this.config.userId = userId
56
+ if (!projectName) {
57
+ throw new Error('Failed to fetch project name from backend111')
58
+ }
59
+
60
60
  this.config.ipaddress = ipaddress
61
- this.config.systemUserId = userId || '' // Set to empty string if not provided
61
+ this.config.systemUserId = systemUserId // Set to empty string if not provided
62
+ this.config.projectName = projectName
63
+ this.config.customerId = this._generateId()
64
+ this.config.sessionId = this._generateId()
62
65
  this._isInitialized = true
63
66
 
64
67
  // Auto-collect page view if enabled
@@ -111,21 +114,23 @@
111
114
  // Extract userId from response (supports multiple response structures)
112
115
  let userId = null
113
116
  let ipaddress = null
114
-
117
+ let projectName = null
115
118
  // Check if response has a 'data' wrapper
116
119
  if (responseData?.data) {
117
120
  userId = responseData?.data?.userId
118
121
  ipaddress = responseData?.data?.ipaddress
122
+ projectName = responseData?.data?.projectName
119
123
  } else {
120
124
  userId = responseData?.userId
121
125
  ipaddress = responseData?.ipaddress
126
+ projectName = responseData?.projectName
122
127
  }
123
128
 
124
129
  if (!userId) {
125
130
  throw new Error('User ID not found in API response')
126
131
  }
127
132
 
128
- return { userId, ipaddress }
133
+ return { systemUserId: userId, ipaddress, projectName }
129
134
  } catch (error) {
130
135
  clearTimeout(timeoutId)
131
136
  throw error
@@ -156,16 +161,54 @@
156
161
  throw new Error('Event name is required')
157
162
  }
158
163
 
164
+ // Validate event name length
165
+ if (typeof eventName !== 'string') {
166
+ throw new Error('Event name must be a string')
167
+ }
168
+
169
+ const eventNameLength = eventName.trim().length
170
+ if (eventNameLength < 4 || eventNameLength > 50) {
171
+ throw new Error('Event name must be between 5 and 50 characters')
172
+ }
173
+
174
+ // Validate properties is an object
175
+ if (properties !== null && (typeof properties !== 'object' || Array.isArray(properties))) {
176
+ throw new Error('Properties must be an object')
177
+ }
178
+
179
+ // Validate properties size (max 16KB)
180
+ if (properties && typeof properties === 'object') {
181
+ const propertiesJson = JSON.stringify(properties)
182
+ let propertiesSize
183
+
184
+ // Calculate size in bytes (works in both browser and Node.js)
185
+ if (typeof Blob !== 'undefined') {
186
+ propertiesSize = new Blob([propertiesJson]).size
187
+ } else if (typeof TextEncoder !== 'undefined') {
188
+ propertiesSize = new TextEncoder().encode(propertiesJson).length
189
+ } else if (typeof Buffer !== 'undefined') {
190
+ propertiesSize = Buffer.byteLength(propertiesJson, 'utf8')
191
+ } else {
192
+ // Fallback: approximate size using string length (UTF-8)
193
+ propertiesSize = propertiesJson.length
194
+ }
195
+
196
+ const maxSize = 16 * 1024 // 16KB in bytes
197
+ if (propertiesSize > maxSize) {
198
+ throw new Error(`Properties object size (${propertiesSize} bytes) exceeds maximum allowed size of 16KB`)
199
+ }
200
+ }
201
+
159
202
  const eventData = this._buildEventPayload({
160
203
  eventType: options.eventType || 'custom',
161
204
  eventName,
162
205
  eventKey: options.eventKey || this._sanitizeEventName(eventName),
163
206
  properties,
164
- sessionId: properties.sessionId || options.sessionId,
207
+ sessionId: properties.sessionId || options.sessionId || this.config.sessionId,
165
208
  context: options.context || {},
166
209
  traits: options.traits || {},
167
- ipaddress: options.ipaddress || this.config.ipaddress,
168
- customId: properties.userId || options.userId
210
+ ipaddress: properties.ipaddress || options.ipaddress || this.config.ipaddress,
211
+ customerId: properties.userId || properties.customerId || options.userId || options.customerId || this.config.customerId,
169
212
  })
170
213
  return this._sendEvent(eventData)
171
214
  }
@@ -178,11 +221,10 @@
178
221
  const timestamp = Date.now()
179
222
  const eventId = this._generateUUID()
180
223
  const requestId = this._generateRequestId()
181
- const userId = data.customId || this.config.userId
224
+ const userId = data.customerId // actual customer id from app
182
225
 
183
226
  // system_user_id comes from API response only, default to empty string if not available
184
227
  const systemUserId = this.config.systemUserId || ''
185
- const finalUserId = userId
186
228
 
187
229
  // Build flat event payload (matching staging.js structure)
188
230
  return {
@@ -193,13 +235,13 @@
193
235
  timestamp: timestamp,
194
236
 
195
237
  // User and session
196
- user_id: finalUserId,
238
+ user_id: userId,
197
239
  session_id: data.sessionId || this.config.sessionId,
198
240
  system_user_id: systemUserId,
199
241
 
200
242
  // Project information
201
243
  project_id: this.config.projectId,
202
- project_name: this.config.projectName || '',
244
+ project_name: this.config.projectName,
203
245
 
204
246
  // Device information (flattened)
205
247
  device: this._deviceInfo.device.type,
@@ -275,7 +317,6 @@
275
317
  try {
276
318
  // Validate mandatory fields before sending
277
319
  this._validateMandatoryFields(eventData)
278
-
279
320
  const headers = {
280
321
  'Content-Type': 'application/json'
281
322
  }
@@ -495,14 +536,6 @@
495
536
  }
496
537
  }
497
538
 
498
- /**
499
- * Generate session ID
500
- * @private
501
- */
502
- _generateSessionId () {
503
- return 'sess_' + this._generateId()
504
- }
505
-
506
539
  /**
507
540
  * Generate UUID v4
508
541
  * @private