riuve-rn 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 (43) hide show
  1. package/README.md +39 -5
  2. package/dist/Riuve.d.ts +31 -0
  3. package/dist/Riuve.d.ts.map +1 -1
  4. package/dist/Riuve.js +164 -6
  5. package/dist/adapters/deviceInfo/ExpoDeviceInfo.d.ts.map +1 -1
  6. package/dist/adapters/deviceInfo/ExpoDeviceInfo.js +35 -0
  7. package/dist/adapters/deviceInfo/FallbackDeviceInfo.d.ts.map +1 -1
  8. package/dist/adapters/deviceInfo/FallbackDeviceInfo.js +15 -0
  9. package/dist/adapters/deviceInfo/NativeDeviceInfo.d.ts.map +1 -1
  10. package/dist/adapters/deviceInfo/NativeDeviceInfo.js +43 -1
  11. package/dist/adapters/deviceInfo/types.d.ts +13 -0
  12. package/dist/adapters/deviceInfo/types.d.ts.map +1 -1
  13. package/dist/constants.d.ts +3 -0
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/constants.js +4 -1
  16. package/dist/core/ContextCollector.d.ts +28 -0
  17. package/dist/core/ContextCollector.d.ts.map +1 -0
  18. package/dist/core/ContextCollector.js +92 -0
  19. package/dist/core/DeviceInfo.d.ts.map +1 -1
  20. package/dist/core/DeviceInfo.js +2 -0
  21. package/dist/index.d.ts +2 -2
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +2 -1
  24. package/dist/managers/AutoTrackManager.d.ts +56 -0
  25. package/dist/managers/AutoTrackManager.d.ts.map +1 -0
  26. package/dist/managers/AutoTrackManager.js +141 -0
  27. package/dist/managers/BatchManager.d.ts.map +1 -1
  28. package/dist/managers/BatchManager.js +4 -0
  29. package/dist/managers/SessionManager.d.ts +49 -0
  30. package/dist/managers/SessionManager.d.ts.map +1 -0
  31. package/dist/managers/SessionManager.js +126 -0
  32. package/dist/managers/SuperPropertiesManager.d.ts +34 -0
  33. package/dist/managers/SuperPropertiesManager.d.ts.map +1 -0
  34. package/dist/managers/SuperPropertiesManager.js +71 -0
  35. package/dist/types/api.d.ts +2 -1
  36. package/dist/types/api.d.ts.map +1 -1
  37. package/dist/types/config.d.ts +20 -0
  38. package/dist/types/config.d.ts.map +1 -1
  39. package/dist/types/events.d.ts +45 -0
  40. package/dist/types/events.d.ts.map +1 -1
  41. package/dist/types/storage.d.ts +10 -0
  42. package/dist/types/storage.d.ts.map +1 -1
  43. package/package.json +1 -1
package/README.md CHANGED
@@ -55,14 +55,24 @@ or
55
55
  yarn add riuve-rn
56
56
  ```
57
57
 
58
- ### 2. Install Required Dependencies
58
+ ### 2. Install a Storage Backend
59
59
 
60
- **AsyncStorage** is required for the SDK to function:
60
+ The SDK needs a storage backend for persisting events and user data. Choose **one** of the following:
61
+
62
+ **Option A: AsyncStorage (default)**
61
63
 
62
64
  ```bash
63
65
  npm install @react-native-async-storage/async-storage
64
66
  ```
65
67
 
68
+ **Option B: MMKV (recommended for performance)**
69
+
70
+ ```bash
71
+ npm install react-native-mmkv
72
+ ```
73
+
74
+ > MMKV is a high-performance synchronous storage library. If your project already uses MMKV, you can use it with the SDK — no need to install AsyncStorage. See [MMKV Storage](#6-mmkv-storage) for setup.
75
+
66
76
  ### 3. (Optional) Expo Modules
67
77
 
68
78
  If you're using Expo, install these for device info and network monitoring:
@@ -263,7 +273,27 @@ const token = await Notifications.getExpoPushTokenAsync();
263
273
  await Riuve.setFcmToken(token.data);
264
274
  ```
265
275
 
266
- ### 5. Locale / Language Override
276
+ ### 5. MMKV Storage
277
+
278
+ By default the SDK uses AsyncStorage. If your project uses `react-native-mmkv`, you can pass it as a custom storage adapter for better performance:
279
+
280
+ ```typescript
281
+ import { MMKV } from 'react-native-mmkv';
282
+ import Riuve, { MMKVStorageAdapter } from 'riuve-rn';
283
+
284
+ const mmkv = new MMKV({ id: 'riuve-storage' });
285
+
286
+ await Riuve.initialize('api_key', {
287
+ storage: new MMKVStorageAdapter(mmkv),
288
+ });
289
+ ```
290
+
291
+ **Why MMKV?**
292
+ - Synchronous reads/writes (no async overhead)
293
+ - ~30x faster than AsyncStorage
294
+ - No need to install AsyncStorage if you already use MMKV
295
+
296
+ ### 6. Locale / Language Override
267
297
 
268
298
  Override the device locale so the backend session uses your chosen language (e.g. for localized push notifications):
269
299
 
@@ -427,6 +457,10 @@ await Riuve.initialize('api_key', {
427
457
  maxQueueSize: 1000, // Maximum queue size (default: 1000)
428
458
  eventRetentionDays: 7, // Days to keep failed events (default: 7)
429
459
 
460
+ // Storage
461
+ storage: undefined, // Custom storage adapter (default: AsyncStorageAdapter)
462
+ // Use new MMKVStorageAdapter(mmkv) for MMKV
463
+
430
464
  // Automatic Operations
431
465
  autoFlushOnBackground: true, // Auto-flush on background (default: true)
432
466
  });
@@ -883,5 +917,5 @@ MIT
883
917
 
884
918
  ---
885
919
 
886
- **Last Updated:** 2026-02-07
887
- **SDK Version:** 1.0.2
920
+ **Last Updated:** 2026-02-25
921
+ **SDK Version:** 1.0.5
package/dist/Riuve.d.ts CHANGED
@@ -11,6 +11,9 @@ declare class RiuveSDK {
11
11
  private identityManager;
12
12
  private networkManager;
13
13
  private batchManager;
14
+ private sessionManager;
15
+ private superPropertiesManager;
16
+ private autoTrackManager;
14
17
  private appStateSubscription;
15
18
  private pendingEvents;
16
19
  /**
@@ -33,6 +36,26 @@ declare class RiuveSDK {
33
36
  * Tracks an event
34
37
  */
35
38
  track(eventName: string, eventProperties?: Record<string, any>): Promise<void>;
39
+ /**
40
+ * Tracks a screen view (convenience method)
41
+ */
42
+ trackScreen(screenName: string, properties?: Record<string, any>): Promise<void>;
43
+ /**
44
+ * Registers super properties that are attached to every event
45
+ */
46
+ registerSuperProperties(properties: Record<string, any>): Promise<void>;
47
+ /**
48
+ * Registers super properties only if not already set
49
+ */
50
+ registerSuperPropertiesOnce(properties: Record<string, any>): Promise<void>;
51
+ /**
52
+ * Unregisters a single super property
53
+ */
54
+ unregisterSuperProperty(key: string): Promise<void>;
55
+ /**
56
+ * Gets the current session ID
57
+ */
58
+ getSessionId(): string | null;
36
59
  /**
37
60
  * Sets the FCM token for push notifications
38
61
  */
@@ -73,6 +96,14 @@ declare class RiuveSDK {
73
96
  * Checks if the SDK is initialized
74
97
  */
75
98
  isReady(): boolean;
99
+ /**
100
+ * Internal track method (skips super properties merge - used by auto-track and session events)
101
+ */
102
+ private trackInternal;
103
+ /**
104
+ * Merges event properties with super properties
105
+ */
106
+ private mergeWithSuperProperties;
76
107
  /**
77
108
  * Sets up app state listener for background flush
78
109
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Riuve.d.ts","sourceRoot":"","sources":["../src/Riuve.ts"],"names":[],"mappings":"AAAA;;GAEG;AAWH,OAAO,KAAK,EAAE,WAAW,EAAS,MAAM,SAAS,CAAC;AAWlD,cAAM,QAAQ;IACZ,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAyB;IAChD,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,aAAa,CAAkB;IAEvC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAA6B;IAEjD,OAAO,CAAC,oBAAoB,CAAa;IACzC,OAAO,CAAC,aAAa,CAA4F;IAEjH;;OAEG;IACH,OAAO;IAEP;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,QAAQ;IAO9B;;OAEG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAmI9F;;OAEG;IACG,QAAQ,CACZ,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GACnC,OAAO,CAAC,IAAI,CAAC;IAuChB;;OAEG;IACG,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDpF;;OAEG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC/C;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAc5B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB5B;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAO/B;;OAEG;IACH,iBAAiB,IAAI,MAAM,GAAG,IAAI;IAOlC;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB9C;;OAEG;IACH,SAAS,IAAI,WAAW,GAAG,IAAI;IAI/B;;OAEG;IACH,YAAY,IAAI,MAAM;IAOtB;;OAEG;IACG,mBAAmB,IAAI,OAAO,CAAC,MAAM,CAAC;IAO5C;;OAEG;IACH,OAAO,IAAI,OAAO;IAIlB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAc7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAMzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA4B/B;AAGD,QAAA,MAAM,KAAK,UAAyB,CAAC;AAErC,eAAe,KAAK,CAAC"}
1
+ {"version":3,"file":"Riuve.d.ts","sourceRoot":"","sources":["../src/Riuve.ts"],"names":[],"mappings":"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"}
package/dist/Riuve.js CHANGED
@@ -8,10 +8,14 @@ const react_native_1 = require("react-native");
8
8
  const EventQueue_1 = require("./core/EventQueue");
9
9
  const ApiClient_1 = require("./core/ApiClient");
10
10
  const DeviceInfo_1 = require("./core/DeviceInfo");
11
+ const ContextCollector_1 = require("./core/ContextCollector");
11
12
  const Storage_1 = require("./core/Storage");
12
13
  const IdentityManager_1 = require("./managers/IdentityManager");
13
14
  const NetworkManager_1 = require("./managers/NetworkManager");
14
15
  const BatchManager_1 = require("./managers/BatchManager");
16
+ const SessionManager_1 = require("./managers/SessionManager");
17
+ const SuperPropertiesManager_1 = require("./managers/SuperPropertiesManager");
18
+ const AutoTrackManager_1 = require("./managers/AutoTrackManager");
15
19
  const constants_1 = require("./constants");
16
20
  const logger_1 = require("./utils/logger");
17
21
  const validators_1 = require("./utils/validators");
@@ -27,6 +31,9 @@ class RiuveSDK {
27
31
  this.identityManager = null;
28
32
  this.networkManager = null;
29
33
  this.batchManager = null;
34
+ this.sessionManager = null;
35
+ this.superPropertiesManager = null;
36
+ this.autoTrackManager = null;
30
37
  this.appStateSubscription = null;
31
38
  this.pendingEvents = [];
32
39
  }
@@ -70,6 +77,31 @@ class RiuveSDK {
70
77
  const anonymousId = await this.identityManager.initialize();
71
78
  this.networkManager = new NetworkManager_1.NetworkManager();
72
79
  await this.networkManager.initialize();
80
+ // Initialize session manager
81
+ this.sessionManager = new SessionManager_1.SessionManager(this.config.sessionTimeout);
82
+ const autoTrackConfig = this.config.autoTrack || {};
83
+ this.sessionManager.setCallbacks(
84
+ // onSessionStart
85
+ (sessionId) => {
86
+ if (autoTrackConfig.sessions !== false) {
87
+ this.trackInternal('$session_start', { session_id: sessionId }).catch((err) => logger_1.logger.error('Failed to track $session_start:', err));
88
+ }
89
+ },
90
+ // onSessionEnd
91
+ (sessionId, duration) => {
92
+ if (autoTrackConfig.sessions !== false) {
93
+ this.trackInternal('$session_end', {
94
+ session_id: sessionId,
95
+ session_duration_ms: duration,
96
+ }).catch((err) => logger_1.logger.error('Failed to track $session_end:', err));
97
+ }
98
+ });
99
+ const sessionId = await this.sessionManager.initialize();
100
+ // Wire session ID into context collector
101
+ ContextCollector_1.contextCollector.setSessionId(sessionId);
102
+ // Initialize super properties
103
+ this.superPropertiesManager = new SuperPropertiesManager_1.SuperPropertiesManager();
104
+ await this.superPropertiesManager.initialize();
73
105
  // Initialize API client with hardcoded base URL
74
106
  this.apiClient = new ApiClient_1.ApiClient(constants_1.API_BASE_URL, this.config.apiKey, this.config.maxRetries, this.config.retryDelay, this.config.requestTimeout);
75
107
  // Initialize event queue
@@ -103,10 +135,33 @@ class RiuveSDK {
103
135
  if (this.config.autoFlushOnBackground) {
104
136
  this.setupAppStateListener();
105
137
  }
138
+ // Process immediate events FIRST (e.g. app_opened) — before any pending events
139
+ const immediateEvents = this.config.immediateEvents;
140
+ if (immediateEvents && immediateEvents.length > 0) {
141
+ const anonId = this.identityManager.getAnonymousId();
142
+ const externalUserId = this.identityManager.getExternalUserId();
143
+ for (const ie of immediateEvents) {
144
+ try {
145
+ const event = {
146
+ id: (0, uuid_1.generateUUID)(),
147
+ name: ie.name,
148
+ properties: ie.properties,
149
+ timestamp: Date.now(),
150
+ anonymousId: anonId,
151
+ externalUserId: externalUserId || undefined,
152
+ };
153
+ await this.eventQueue.enqueue(event);
154
+ logger_1.logger.info(`Immediate event enqueued: ${ie.name}`);
155
+ }
156
+ catch (error) {
157
+ logger_1.logger.error(`Failed to enqueue immediate event '${ie.name}':`, error);
158
+ }
159
+ }
160
+ }
106
161
  // Process pending events (events that were tracked before initialization)
107
162
  if (this.pendingEvents.length > 0) {
108
163
  logger_1.logger.info(`Processing ${this.pendingEvents.length} pending events...`);
109
- const anonymousId = this.identityManager.getAnonymousId();
164
+ const anonId = this.identityManager.getAnonymousId();
110
165
  const externalUserId = this.identityManager.getExternalUserId();
111
166
  let processedCount = 0;
112
167
  for (const pendingEvent of this.pendingEvents) {
@@ -114,9 +169,9 @@ class RiuveSDK {
114
169
  const event = {
115
170
  id: (0, uuid_1.generateUUID)(),
116
171
  name: pendingEvent.eventName,
117
- properties: pendingEvent.eventProperties,
172
+ properties: this.mergeWithSuperProperties(pendingEvent.eventProperties),
118
173
  timestamp: pendingEvent.timestamp, // Use original timestamp
119
- anonymousId,
174
+ anonymousId: anonId,
120
175
  externalUserId: externalUserId || undefined,
121
176
  };
122
177
  await this.eventQueue.enqueue(event);
@@ -131,6 +186,10 @@ class RiuveSDK {
131
186
  this.pendingEvents = []; // Clear pending events
132
187
  }
133
188
  this.isInitialized = true;
189
+ // Initialize auto-track manager (after isInitialized = true so tracking works)
190
+ this.autoTrackManager = new AutoTrackManager_1.AutoTrackManager(autoTrackConfig);
191
+ this.autoTrackManager.setTrackFunction((name, props) => this.trackInternal(name, props));
192
+ await this.autoTrackManager.start(deviceInfo.app_version);
134
193
  // Flush any offline queue
135
194
  await this.batchManager.flushOfflineQueue();
136
195
  }
@@ -171,6 +230,10 @@ class RiuveSDK {
171
230
  else {
172
231
  logger_1.logger.warn('Offline - user will be identified when online');
173
232
  }
233
+ // Track $identify auto event
234
+ if (this.autoTrackManager) {
235
+ await this.autoTrackManager.trackIdentify(externalUserId, userProperties);
236
+ }
174
237
  }
175
238
  catch (error) {
176
239
  logger_1.logger.error('Failed to identify user:', error);
@@ -202,12 +265,16 @@ class RiuveSDK {
202
265
  logger_1.logger.info(` Pending queue size: ${this.pendingEvents.length}`);
203
266
  return;
204
267
  }
268
+ // Touch session to keep it alive
269
+ await this.sessionManager.touch();
270
+ // Merge super properties with event properties
271
+ const mergedProperties = this.mergeWithSuperProperties(eventProperties);
205
272
  // SDK is initialized, proceed with normal flow
206
273
  try {
207
274
  const event = {
208
275
  id: (0, uuid_1.generateUUID)(),
209
276
  name: eventName,
210
- properties: eventProperties,
277
+ properties: mergedProperties,
211
278
  timestamp: Date.now(),
212
279
  anonymousId: this.identityManager.getAnonymousId(),
213
280
  externalUserId: this.identityManager.getExternalUserId() || undefined,
@@ -216,7 +283,7 @@ class RiuveSDK {
216
283
  // Add to queue
217
284
  await this.eventQueue.enqueue(event);
218
285
  const queueSizeAfter = this.eventQueue.size();
219
- const propsStr = eventProperties ? this.truncateJson(JSON.stringify(eventProperties), 150) : 'none';
286
+ const propsStr = mergedProperties ? this.truncateJson(JSON.stringify(mergedProperties), 150) : 'none';
220
287
  logger_1.logger.info(`Event tracked: ${eventName}`);
221
288
  logger_1.logger.info(` Properties: ${propsStr}`);
222
289
  logger_1.logger.info(` Event ID: ${event.id.substring(0, 8)}...`);
@@ -229,6 +296,50 @@ class RiuveSDK {
229
296
  throw error;
230
297
  }
231
298
  }
299
+ /**
300
+ * Tracks a screen view (convenience method)
301
+ */
302
+ async trackScreen(screenName, properties) {
303
+ // Update context collector with current screen
304
+ ContextCollector_1.contextCollector.setCurrentScreen(screenName);
305
+ // Track via auto-track manager if available, otherwise track directly
306
+ if (this.autoTrackManager) {
307
+ await this.autoTrackManager.trackScreenView(screenName, properties);
308
+ }
309
+ else {
310
+ await this.track('$screen_view', { screen_name: screenName, ...properties });
311
+ }
312
+ }
313
+ /**
314
+ * Registers super properties that are attached to every event
315
+ */
316
+ async registerSuperProperties(properties) {
317
+ this.ensureInitialized();
318
+ await this.superPropertiesManager.register(properties);
319
+ }
320
+ /**
321
+ * Registers super properties only if not already set
322
+ */
323
+ async registerSuperPropertiesOnce(properties) {
324
+ this.ensureInitialized();
325
+ await this.superPropertiesManager.registerOnce(properties);
326
+ }
327
+ /**
328
+ * Unregisters a single super property
329
+ */
330
+ async unregisterSuperProperty(key) {
331
+ this.ensureInitialized();
332
+ await this.superPropertiesManager.unregister(key);
333
+ }
334
+ /**
335
+ * Gets the current session ID
336
+ */
337
+ getSessionId() {
338
+ if (!this.isInitialized || !this.sessionManager) {
339
+ return null;
340
+ }
341
+ return this.sessionManager.getSessionId();
342
+ }
232
343
  /**
233
344
  * Sets the FCM token for push notifications
234
345
  */
@@ -292,6 +403,10 @@ class RiuveSDK {
292
403
  await this.flush();
293
404
  // Reset identity
294
405
  await this.identityManager.reset();
406
+ // Reset session
407
+ await this.sessionManager.reset();
408
+ // Clear super properties
409
+ await this.superPropertiesManager.clearAll();
295
410
  // Clear FCM token
296
411
  await Storage_1.storage.remove('FCM_TOKEN');
297
412
  logger_1.logger.info('SDK reset successfully');
@@ -375,6 +490,43 @@ class RiuveSDK {
375
490
  isReady() {
376
491
  return this.isInitialized;
377
492
  }
493
+ /**
494
+ * Internal track method (skips super properties merge - used by auto-track and session events)
495
+ */
496
+ async trackInternal(eventName, eventProperties) {
497
+ if (!this.isInitialized)
498
+ return;
499
+ try {
500
+ const event = {
501
+ id: (0, uuid_1.generateUUID)(),
502
+ name: eventName,
503
+ properties: eventProperties,
504
+ timestamp: Date.now(),
505
+ anonymousId: this.identityManager.getAnonymousId(),
506
+ externalUserId: this.identityManager.getExternalUserId() || undefined,
507
+ };
508
+ await this.eventQueue.enqueue(event);
509
+ logger_1.logger.debug(`Internal event tracked: ${eventName}`);
510
+ }
511
+ catch (error) {
512
+ logger_1.logger.error(`Failed to track internal event '${eventName}':`, error);
513
+ }
514
+ }
515
+ /**
516
+ * Merges event properties with super properties
517
+ */
518
+ mergeWithSuperProperties(eventProperties) {
519
+ const superProps = this.superPropertiesManager?.getAll() || {};
520
+ const hasSuperProps = Object.keys(superProps).length > 0;
521
+ if (!hasSuperProps && !eventProperties)
522
+ return undefined;
523
+ if (!hasSuperProps)
524
+ return eventProperties;
525
+ if (!eventProperties)
526
+ return superProps;
527
+ // Event properties take precedence over super properties
528
+ return { ...superProps, ...eventProperties };
529
+ }
378
530
  /**
379
531
  * Sets up app state listener for background flush
380
532
  */
@@ -420,10 +572,16 @@ class RiuveSDK {
420
572
  }
421
573
  this.eventQueue.destroy();
422
574
  }
423
- // Cleanup network manager
575
+ // Cleanup managers
424
576
  if (this.networkManager) {
425
577
  this.networkManager.cleanup();
426
578
  }
579
+ if (this.sessionManager) {
580
+ this.sessionManager.cleanup();
581
+ }
582
+ if (this.autoTrackManager) {
583
+ this.autoTrackManager.cleanup();
584
+ }
427
585
  // Remove app state listener
428
586
  if (this.appStateSubscription) {
429
587
  this.appStateSubscription.remove();
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/ExpoDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEjE,qBAAa,cAAe,YAAW,iBAAiB;IACtD,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IA4CxC,SAAS,IAAI,cAAc,GAAG,IAAI;CAGnC"}
1
+ {"version":3,"file":"ExpoDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/ExpoDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGjE,qBAAa,cAAe,YAAW,iBAAiB;IACtD,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IA6ExC,SAAS,IAAI,cAAc,GAAG,IAAI;CAGnC"}
@@ -41,6 +41,7 @@ var __importStar = (this && this.__importStar) || (function () {
41
41
  Object.defineProperty(exports, "__esModule", { value: true });
42
42
  exports.ExpoDeviceInfo = void 0;
43
43
  const react_native_1 = require("react-native");
44
+ const constants_1 = require("../../constants");
44
45
  class ExpoDeviceInfo {
45
46
  constructor() {
46
47
  this.cachedInfo = null;
@@ -60,6 +61,23 @@ class ExpoDeviceInfo {
60
61
  const platform = react_native_1.Platform.OS;
61
62
  const systemVersion = Device.osVersion || react_native_1.Platform.Version.toString();
62
63
  const osVersion = `${react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android'} ${systemVersion}`;
64
+ // Get screen dimensions
65
+ const screen = react_native_1.Dimensions.get('screen');
66
+ // Get timezone
67
+ let timezone;
68
+ try {
69
+ timezone = Localization.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone;
70
+ }
71
+ catch {
72
+ try {
73
+ timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
74
+ }
75
+ catch { }
76
+ }
77
+ // Map expo device type: 1=PHONE, 2=TABLET, 3=DESKTOP, 4=TV
78
+ const expoDeviceTypeMap = {
79
+ 1: 'phone', 2: 'tablet', 3: 'desktop', 4: 'tv',
80
+ };
63
81
  const deviceInfo = {
64
82
  os_version: osVersion,
65
83
  device_model: Device.modelName || 'Unknown',
@@ -68,18 +86,35 @@ class ExpoDeviceInfo {
68
86
  platform,
69
87
  manufacturer: Device.manufacturer || undefined,
70
88
  brand: Device.brand || undefined,
89
+ screen_width: Math.round(screen.width),
90
+ screen_height: Math.round(screen.height),
91
+ screen_density: react_native_1.PixelRatio.get(),
92
+ total_memory: Device.totalMemory || undefined,
93
+ build_number: Application.nativeBuildVersion || undefined,
94
+ sdk_version: constants_1.SDK_VERSION,
95
+ app_name: Application.applicationName || undefined,
96
+ app_namespace: Application.applicationId || undefined,
97
+ timezone,
98
+ device_type: Device.deviceType != null ? (expoDeviceTypeMap[Device.deviceType] || 'unknown') : undefined,
99
+ device_name: Device.deviceName || undefined,
100
+ is_emulator: Device.isDevice === false ? true : Device.isDevice === true ? false : undefined,
71
101
  };
72
102
  this.cachedInfo = deviceInfo;
73
103
  return deviceInfo;
74
104
  }
75
105
  catch (error) {
76
106
  // Fallback if expo modules fail
107
+ const screen = react_native_1.Dimensions.get('screen');
77
108
  const fallbackInfo = {
78
109
  os_version: react_native_1.Platform.Version.toString(),
79
110
  device_model: 'Unknown',
80
111
  app_version: '1.0.0',
81
112
  locale: 'en-US',
82
113
  platform: react_native_1.Platform.OS,
114
+ screen_width: Math.round(screen.width),
115
+ screen_height: Math.round(screen.height),
116
+ screen_density: react_native_1.PixelRatio.get(),
117
+ sdk_version: constants_1.SDK_VERSION,
83
118
  };
84
119
  return fallbackInfo;
85
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FallbackDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/FallbackDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEjE,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAqBxC,SAAS,IAAI,cAAc,GAAG,IAAI;CAGnC"}
1
+ {"version":3,"file":"FallbackDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/FallbackDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGjE,qBAAa,kBAAmB,YAAW,iBAAiB;IAC1D,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAoCxC,SAAS,IAAI,cAAc,GAAG,IAAI;CAGnC"}
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.FallbackDeviceInfo = void 0;
10
10
  const react_native_1 = require("react-native");
11
+ const constants_1 = require("../../constants");
11
12
  class FallbackDeviceInfo {
12
13
  constructor() {
13
14
  this.cachedInfo = null;
@@ -19,12 +20,26 @@ class FallbackDeviceInfo {
19
20
  const platform = react_native_1.Platform.OS;
20
21
  const version = react_native_1.Platform.Version.toString();
21
22
  const osVersion = `${react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android'} ${version}`;
23
+ // Get screen dimensions
24
+ const screen = react_native_1.Dimensions.get('screen');
25
+ // Get timezone
26
+ let timezone;
27
+ try {
28
+ timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
29
+ }
30
+ catch { }
22
31
  const deviceInfo = {
23
32
  os_version: osVersion,
24
33
  device_model: 'Unknown',
25
34
  app_version: '1.0.0',
26
35
  locale: 'en-US',
27
36
  platform,
37
+ screen_width: Math.round(screen.width),
38
+ screen_height: Math.round(screen.height),
39
+ screen_density: react_native_1.PixelRatio.get(),
40
+ sdk_version: constants_1.SDK_VERSION,
41
+ timezone,
42
+ device_type: 'phone',
28
43
  };
29
44
  this.cachedInfo = deviceInfo;
30
45
  return deviceInfo;
@@ -1 +1 @@
1
- {"version":3,"file":"NativeDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/NativeDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAUjE,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAoDxC,SAAS,IAAI,cAAc,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,SAAS;CAiBlB"}
1
+ {"version":3,"file":"NativeDeviceInfo.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/NativeDeviceInfo.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAWjE,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,UAAU,CAA+B;IAE3C,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IAuGxC,SAAS,IAAI,cAAc,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,SAAS;CAiBlB"}
@@ -8,6 +8,7 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.NativeDeviceInfo = void 0;
10
10
  const react_native_1 = require("react-native");
11
+ const constants_1 = require("../../constants");
11
12
  // Dynamic require to avoid Metro bundling error when module is not installed
12
13
  let DeviceInfo;
13
14
  try {
@@ -25,17 +26,40 @@ class NativeDeviceInfo {
25
26
  return this.cachedInfo;
26
27
  }
27
28
  try {
28
- const [systemVersion, model, version, manufacturer, brand,] = await Promise.all([
29
+ const [systemVersion, model, version, manufacturer, brand, totalMemory, buildNumber, carrier, appName, bundleId, deviceType, deviceName, isEmulator,] = await Promise.all([
29
30
  DeviceInfo.getSystemVersion(),
30
31
  DeviceInfo.getModel(),
31
32
  DeviceInfo.getVersion(),
32
33
  DeviceInfo.getManufacturer(),
33
34
  DeviceInfo.getBrand(),
35
+ DeviceInfo.getTotalMemory().catch(() => undefined),
36
+ DeviceInfo.getBuildNumber().catch(() => undefined),
37
+ DeviceInfo.getCarrier().catch(() => undefined),
38
+ DeviceInfo.getApplicationName().catch(() => undefined),
39
+ DeviceInfo.getBundleId().catch(() => undefined),
40
+ DeviceInfo.getDeviceType().catch(() => undefined),
41
+ DeviceInfo.getDeviceName().catch(() => undefined),
42
+ DeviceInfo.isEmulator().catch(() => undefined),
34
43
  ]);
35
44
  // Get locale
36
45
  const locale = this.getLocale();
37
46
  const platform = react_native_1.Platform.OS === 'ios' ? 'ios' : 'android';
38
47
  const osVersion = `${react_native_1.Platform.OS === 'ios' ? 'iOS' : 'Android'} ${systemVersion}`;
48
+ // Get screen dimensions
49
+ const screen = react_native_1.Dimensions.get('screen');
50
+ // Get timezone
51
+ let timezone;
52
+ try {
53
+ timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
54
+ }
55
+ catch { }
56
+ // Map device type from react-native-device-info
57
+ const deviceTypeMap = {
58
+ Handset: 'phone',
59
+ Tablet: 'tablet',
60
+ Tv: 'tv',
61
+ Desktop: 'desktop',
62
+ };
39
63
  const deviceInfo = {
40
64
  os_version: osVersion,
41
65
  device_model: model,
@@ -44,18 +68,36 @@ class NativeDeviceInfo {
44
68
  platform,
45
69
  manufacturer,
46
70
  brand,
71
+ screen_width: Math.round(screen.width),
72
+ screen_height: Math.round(screen.height),
73
+ screen_density: react_native_1.PixelRatio.get(),
74
+ carrier: carrier || undefined,
75
+ total_memory: totalMemory || undefined,
76
+ build_number: buildNumber || undefined,
77
+ sdk_version: constants_1.SDK_VERSION,
78
+ app_name: appName || undefined,
79
+ app_namespace: bundleId || undefined,
80
+ timezone,
81
+ device_type: deviceType ? (deviceTypeMap[deviceType] || 'unknown') : undefined,
82
+ device_name: deviceName || undefined,
83
+ is_emulator: typeof isEmulator === 'boolean' ? isEmulator : undefined,
47
84
  };
48
85
  this.cachedInfo = deviceInfo;
49
86
  return deviceInfo;
50
87
  }
51
88
  catch (error) {
52
89
  // Fallback if native module fails
90
+ const screen = react_native_1.Dimensions.get('screen');
53
91
  const fallbackInfo = {
54
92
  os_version: `${react_native_1.Platform.OS} unknown`,
55
93
  device_model: 'unknown',
56
94
  app_version: '1.0.0',
57
95
  locale: this.getLocale(),
58
96
  platform: react_native_1.Platform.OS === 'ios' ? 'ios' : 'android',
97
+ screen_width: Math.round(screen.width),
98
+ screen_height: Math.round(screen.height),
99
+ screen_density: react_native_1.PixelRatio.get(),
100
+ sdk_version: constants_1.SDK_VERSION,
59
101
  };
60
102
  return fallbackInfo;
61
103
  }
@@ -11,6 +11,19 @@ export interface DeviceInfoType {
11
11
  platform: 'ios' | 'android';
12
12
  manufacturer?: string;
13
13
  brand?: string;
14
+ screen_width?: number;
15
+ screen_height?: number;
16
+ screen_density?: number;
17
+ carrier?: string;
18
+ total_memory?: number;
19
+ build_number?: string;
20
+ sdk_version: string;
21
+ app_name?: string;
22
+ app_namespace?: string;
23
+ timezone?: string;
24
+ device_type?: 'phone' | 'tablet' | 'tv' | 'desktop' | 'unknown';
25
+ device_name?: string;
26
+ is_emulator?: boolean;
14
27
  }
15
28
  export interface DeviceInfoAdapter {
16
29
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAEnC;;OAEG;IACH,SAAS,IAAI,cAAc,GAAG,IAAI,CAAC;CACpC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/adapters/deviceInfo/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IAEpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAEnC;;OAEG;IACH,SAAS,IAAI,cAAc,GAAG,IAAI,CAAC;CACpC"}
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * SDK Constants
3
3
  */
4
+ export declare const SDK_VERSION = "2.0.0";
4
5
  export declare const STORAGE_KEYS: {
5
6
  readonly ANONYMOUS_ID: "@riuve/anonymous_id";
6
7
  readonly EXTERNAL_USER_ID: "@riuve/external_user_id";
@@ -10,6 +11,8 @@ export declare const STORAGE_KEYS: {
10
11
  readonly EVENT_QUEUE: "@riuve/event_queue";
11
12
  readonly FAILED_BATCHES: "@riuve/failed_batches";
12
13
  readonly LOCALE_OVERRIDE: "@riuve/locale_override";
14
+ readonly SESSION_DATA: "@riuve/session_data";
15
+ readonly SUPER_PROPERTIES: "@riuve/super_properties";
13
16
  };
14
17
  export declare const DEFAULT_CONFIG: {
15
18
  readonly batchSize: 10;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY;;;;;;;;;CASf,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;CAWjB,CAAC;AAEX,eAAO,MAAM,YAAY,0BAA0B,CAAC;AAEpD,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;CAQjB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,WAAW,UAAU,CAAC;AAEnC,eAAO,MAAM,YAAY;;;;;;;;;;;CAWf,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;;;;CAWjB,CAAC;AAEX,eAAO,MAAM,YAAY,0BAA0B,CAAC;AAEpD,eAAO,MAAM,aAAa;;;;;CAKhB,CAAC;AAEX,eAAO,MAAM,cAAc;;;;;;;;CAQjB,CAAC"}