respectlytics-react-native 1.0.1 → 2.0.0

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 (50) hide show
  1. package/README.md +43 -34
  2. package/lib/commonjs/EventQueue.js +174 -0
  3. package/lib/commonjs/EventQueue.js.map +1 -0
  4. package/lib/commonjs/NetworkClient.js +158 -0
  5. package/lib/commonjs/NetworkClient.js.map +1 -0
  6. package/lib/commonjs/Respectlytics.js +167 -0
  7. package/lib/commonjs/Respectlytics.js.map +1 -0
  8. package/lib/commonjs/SessionManager.js +75 -0
  9. package/lib/commonjs/SessionManager.js.map +1 -0
  10. package/lib/commonjs/Storage.js +57 -0
  11. package/lib/commonjs/Storage.js.map +1 -0
  12. package/lib/commonjs/index.js +37 -0
  13. package/lib/commonjs/index.js.map +1 -0
  14. package/lib/commonjs/types.js +35 -0
  15. package/lib/commonjs/types.js.map +1 -0
  16. package/lib/module/EventQueue.js +166 -0
  17. package/lib/module/EventQueue.js.map +1 -0
  18. package/lib/module/NetworkClient.js +151 -0
  19. package/lib/module/NetworkClient.js.map +1 -0
  20. package/lib/module/Respectlytics.js +162 -0
  21. package/lib/module/Respectlytics.js.map +1 -0
  22. package/lib/module/SessionManager.js +68 -0
  23. package/lib/module/SessionManager.js.map +1 -0
  24. package/lib/module/Storage.js +50 -0
  25. package/lib/module/Storage.js.map +1 -0
  26. package/lib/module/index.js +23 -0
  27. package/lib/module/index.js.map +1 -0
  28. package/lib/module/types.js +29 -0
  29. package/lib/module/types.js.map +1 -0
  30. package/lib/typescript/EventQueue.d.ts +47 -0
  31. package/lib/typescript/EventQueue.d.ts.map +1 -0
  32. package/lib/typescript/NetworkClient.d.ts +48 -0
  33. package/lib/typescript/NetworkClient.d.ts.map +1 -0
  34. package/lib/typescript/Respectlytics.d.ts +61 -0
  35. package/lib/typescript/Respectlytics.d.ts.map +1 -0
  36. package/lib/typescript/SessionManager.d.ts +39 -0
  37. package/lib/typescript/SessionManager.d.ts.map +1 -0
  38. package/lib/typescript/Storage.d.ts +26 -0
  39. package/lib/typescript/Storage.d.ts.map +1 -0
  40. package/lib/typescript/index.d.ts +18 -0
  41. package/lib/typescript/index.d.ts.map +1 -0
  42. package/lib/typescript/types.d.ts +38 -0
  43. package/lib/typescript/types.d.ts.map +1 -0
  44. package/package.json +2 -2
  45. package/src/NetworkClient.ts +1 -1
  46. package/src/Respectlytics.ts +7 -29
  47. package/src/SessionManager.ts +24 -20
  48. package/src/index.ts +8 -1
  49. package/src/types.ts +5 -2
  50. package/src/UserManager.ts +0 -74
package/README.md CHANGED
@@ -4,15 +4,15 @@
4
4
  [![Platform](https://img.shields.io/badge/platform-iOS%20%7C%20Android-lightgrey.svg)](https://github.com/respectlytics/respectlytics-react-native)
5
5
  [![License](https://img.shields.io/badge/license-Proprietary-blue.svg)](LICENSE)
6
6
 
7
- Official Respectlytics SDK for React Native. Privacy-first analytics with automatic session management, offline event queuing, and zero device identifier collection.
7
+ Official Respectlytics SDK for React Native. Privacy-first, session-based analytics with automatic session management, offline event queuing, and zero device identifier collection.
8
8
 
9
9
  ## Features
10
10
 
11
11
  - 🔒 **Privacy-First**: No device identifiers (IDFA, GAID, Android ID)
12
- - ⚡ **Simple Integration**: 3 lines of code to get started
12
+ - ⚡ **Simple Integration**: 2 lines of code to get started
13
13
  - 📡 **Offline Support**: Events queue automatically and sync when online
14
- - 🔄 **Automatic Sessions**: 30-minute inactivity timeout, handled internally
15
- - 🎯 **Cross-Session Tracking**: Optional persistent user IDs
14
+ - 🔄 **Automatic Sessions**: RAM-only, 2-hour rotation, new session on app restart
15
+ - **Designed for GDPR/ePrivacy compliance** - Potentially consent-free
16
16
  - 📱 **Cross-Platform**: iOS and Android support
17
17
 
18
18
  ## Requirements
@@ -51,14 +51,13 @@ import Respectlytics from 'respectlytics-react-native';
51
51
  // 1. Configure at app startup
52
52
  Respectlytics.configure('your-api-key');
53
53
 
54
- // 2. Enable user tracking (optional)
55
- Respectlytics.identify();
56
-
57
- // 3. Track events
54
+ // 2. Track events
58
55
  Respectlytics.track('purchase');
59
56
  Respectlytics.track('view_product', 'ProductScreen');
60
57
  ```
61
58
 
59
+ That's it! Session management is fully automatic.
60
+
62
61
  ## API Reference
63
62
 
64
63
  ### `configure(apiKey: string)`
@@ -78,47 +77,47 @@ Respectlytics.track('button_clicked');
78
77
  Respectlytics.track('checkout_started', 'CartScreen');
79
78
  ```
80
79
 
81
- ### `identify()`
80
+ ### `flush()`
82
81
 
83
- Enable cross-session user tracking. Generates and persists a random user ID.
82
+ Force send all queued events immediately. Rarely needed - the SDK auto-flushes.
84
83
 
85
84
  ```typescript
86
- Respectlytics.identify();
85
+ await Respectlytics.flush();
87
86
  ```
88
87
 
89
- ### `reset()`
88
+ ## 🔄 Automatic Session Management
90
89
 
91
- Clear the user ID. Call when user logs out.
90
+ Session IDs are managed entirely by the SDK - no configuration needed.
92
91
 
93
- ```typescript
94
- Respectlytics.reset();
95
- ```
92
+ | Behavior | Description |
93
+ |----------|-------------|
94
+ | **New session on app launch** | Every time your app starts, a fresh session begins |
95
+ | **2-hour rotation** | Sessions automatically rotate after 2 hours of use |
96
+ | **RAM-only storage** | Session IDs are never written to disk |
97
+ | **No cross-session tracking** | Each session is independent and anonymous |
96
98
 
97
- ### `flush()`
98
-
99
- Force send all queued events immediately. Rarely needed - the SDK auto-flushes.
100
-
101
- ```typescript
102
- await Respectlytics.flush();
103
- ```
99
+ This RAM-only approach ensures compliance with ePrivacy Directive Article 5(3) - no device storage means no consent requirement for the session identifier.
104
100
 
105
101
  ## Privacy by Design
106
102
 
103
+ Your privacy is our priority. Our mobile analytics solution is meticulously designed to provide valuable insights without compromising your data. We achieve this by collecting only session-based data, using anonymized identifiers that are stored only in your device's memory and renewed every two hours or upon app restart. IP addresses are processed transiently for approximate geolocation (country and region) only and are never stored. This privacy-by-design approach ensures that no personal data is retained, making our solution designed to comply with GDPR and the ePrivacy Directive, potentially enabling analytics without user consent in many jurisdictions.
104
+
107
105
  | What we DON'T collect | Why |
108
106
  |----------------------|-----|
109
107
  | IDFA / GAID | Device advertising IDs can track users across apps |
110
108
  | Device fingerprints | Can be used to identify users without consent |
111
- | IP addresses | Used only for geolocation lookup, then discarded |
109
+ | IP addresses | Processed transiently for geolocation, then discarded |
112
110
  | Custom properties | Prevents accidental PII collection |
111
+ | Persistent user IDs | Cross-session tracking requires consent |
113
112
 
114
113
  | What we DO collect | Purpose |
115
114
  |-------------------|---------|
116
115
  | Event name | Analytics |
117
116
  | Screen name | Navigation analytics |
118
- | Random session ID | Group events in a session |
119
- | Random user ID (opt-in) | Cross-session analytics |
117
+ | Random session ID (RAM-only) | Group events in a session |
120
118
  | Platform, OS version | Debugging |
121
- | App version | Debugging |
119
+ | App version, locale | Debugging |
120
+ | Country, region | Approximate geolocation |
122
121
 
123
122
  ## Automatic Behaviors
124
123
 
@@ -126,7 +125,7 @@ The SDK handles these automatically - no developer action needed:
126
125
 
127
126
  | Feature | Behavior |
128
127
  |---------|----------|
129
- | **Session Management** | New session ID generated on first event, rotates after 30 min inactivity |
128
+ | **Session Management** | New session ID on app launch, rotates after 2 hours |
130
129
  | **Event Batching** | Events queued and sent in batches (max 10 events or 30 seconds) |
131
130
  | **Offline Support** | Events queued when offline, sent when connectivity returns |
132
131
  | **Retry Logic** | Failed requests retry with exponential backoff (max 3 attempts) |
@@ -141,13 +140,23 @@ Events are automatically queued when offline and sent when connectivity returns:
141
140
  3. Queue is flushed when connectivity is restored
142
141
  4. Failed sends are retried with exponential backoff
143
142
 
144
- ## Session Management
143
+ ## Migration from v1.x
144
+
145
+ ### Breaking Changes
146
+
147
+ - `identify()` method removed - no longer needed
148
+ - `reset()` method removed - no longer needed
149
+ - AsyncStorage no longer used for user IDs - sessions are RAM-only
150
+
151
+ ### What to do
152
+
153
+ 1. Remove any calls to `Respectlytics.identify()`
154
+ 2. Remove any calls to `Respectlytics.reset()`
155
+ 3. That's it! Session management is now automatic.
145
156
 
146
- Sessions are managed automatically:
157
+ ### Why This Change?
147
158
 
148
- - New session starts on first event
149
- - Session rotates after 30 minutes of inactivity
150
- - No developer action required
159
+ Storing identifiers on device (AsyncStorage) requires user consent under ePrivacy Directive Article 5(3). In-memory sessions require no consent, making Respectlytics truly consent-free analytics.
151
160
 
152
161
  ## License
153
162
 
@@ -155,6 +164,6 @@ This SDK is provided under a proprietary license. See [LICENSE](LICENSE) for det
155
164
 
156
165
  ## Support
157
166
 
158
- - Documentation: [https://respectlytics.com/docs/](https://respectlytics.com/docs/)
167
+ - Documentation: [https://respectlytics.com/sdk/](https://respectlytics.com/sdk/)
159
168
  - Issues: [https://github.com/respectlytics/respectlytics-react-native/issues](https://github.com/respectlytics/respectlytics-react-native/issues)
160
169
  - Email: respectlytics@loheden.com
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EventQueue = void 0;
7
+ var _reactNative = require("react-native");
8
+ var _netinfo = _interopRequireDefault(require("@react-native-community/netinfo"));
9
+ var _Storage = require("./Storage");
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ /**
12
+ * EventQueue.ts
13
+ * Respectlytics React Native SDK
14
+ *
15
+ * Manages event batching, persistence, and automatic flushing.
16
+ * Events are NEVER lost - they are persisted immediately and retried on failure.
17
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
18
+ */
19
+
20
+ const MAX_QUEUE_SIZE = 10;
21
+ const FLUSH_INTERVAL_MS = 30000; // 30 seconds
22
+ const QUEUE_STORAGE_KEY = 'com.respectlytics.eventQueue';
23
+ class EventQueue {
24
+ events = [];
25
+ isOnline = true;
26
+ flushTimer = null;
27
+ isFlushing = false;
28
+ unsubscribeNetInfo = null;
29
+ appStateSubscription = null;
30
+ constructor(networkClient) {
31
+ this.networkClient = networkClient;
32
+ }
33
+
34
+ /**
35
+ * Initialize the queue - load persisted events and set up listeners
36
+ */
37
+ async start() {
38
+ await this.loadPersistedQueue();
39
+ this.setupNetworkMonitor();
40
+ this.setupAppStateMonitor();
41
+ this.scheduleFlush();
42
+ console.log('[Respectlytics] ✓ Event queue started');
43
+ }
44
+
45
+ /**
46
+ * Stop the queue and clean up resources
47
+ */
48
+ stop() {
49
+ if (this.flushTimer) {
50
+ clearInterval(this.flushTimer);
51
+ this.flushTimer = null;
52
+ }
53
+ if (this.unsubscribeNetInfo) {
54
+ this.unsubscribeNetInfo();
55
+ this.unsubscribeNetInfo = null;
56
+ }
57
+ if (this.appStateSubscription) {
58
+ this.appStateSubscription.remove();
59
+ this.appStateSubscription = null;
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Add an event to the queue
65
+ * CRITICAL: Events are persisted IMMEDIATELY before any async operations
66
+ */
67
+ async add(event) {
68
+ this.events.push(event);
69
+
70
+ // IMMEDIATELY persist before any async operations
71
+ await this.persistQueue();
72
+
73
+ // Check if we should flush
74
+ if (this.events.length >= MAX_QUEUE_SIZE) {
75
+ this.flush();
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Force flush all queued events
81
+ */
82
+ async flush() {
83
+ if (this.isFlushing || this.events.length === 0) {
84
+ return;
85
+ }
86
+ if (!this.isOnline) {
87
+ console.log('[Respectlytics] Offline, skipping flush');
88
+ return;
89
+ }
90
+ if (!this.networkClient.isConfigured()) {
91
+ console.log('[Respectlytics] ⚠️ SDK not configured, skipping flush');
92
+ return;
93
+ }
94
+ this.isFlushing = true;
95
+
96
+ // Take a snapshot of events to send
97
+ const batch = [...this.events];
98
+ this.events = [];
99
+ await this.persistQueue();
100
+ try {
101
+ await this.networkClient.send(batch);
102
+ console.log(`[Respectlytics] ✓ Sent ${batch.length} event(s)`);
103
+ } catch (error) {
104
+ // Re-add failed events to the front of the queue
105
+ this.events = [...batch, ...this.events];
106
+ await this.persistQueue();
107
+ console.log('[Respectlytics] Failed to send events, will retry later');
108
+ } finally {
109
+ this.isFlushing = false;
110
+ }
111
+ }
112
+
113
+ /**
114
+ * Get current queue size (for testing)
115
+ */
116
+ getQueueSize() {
117
+ return this.events.length;
118
+ }
119
+
120
+ // MARK: - Private Helpers
121
+
122
+ scheduleFlush() {
123
+ if (this.flushTimer) {
124
+ clearInterval(this.flushTimer);
125
+ }
126
+ this.flushTimer = setInterval(() => {
127
+ this.flush();
128
+ }, FLUSH_INTERVAL_MS);
129
+ }
130
+ setupNetworkMonitor() {
131
+ this.unsubscribeNetInfo = _netinfo.default.addEventListener(state => {
132
+ const wasOffline = !this.isOnline;
133
+ this.isOnline = state.isConnected ?? false;
134
+
135
+ // If we just came online, try to flush
136
+ if (wasOffline && this.isOnline) {
137
+ console.log('[Respectlytics] Network restored, flushing queue');
138
+ this.flush();
139
+ }
140
+ });
141
+ }
142
+ setupAppStateMonitor() {
143
+ this.appStateSubscription = _reactNative.AppState.addEventListener('change', nextAppState => {
144
+ // Flush when app goes to background
145
+ if (nextAppState === 'background' || nextAppState === 'inactive') {
146
+ this.flush();
147
+ }
148
+ });
149
+ }
150
+ async persistQueue() {
151
+ try {
152
+ await _Storage.Storage.setItem(QUEUE_STORAGE_KEY, JSON.stringify(this.events));
153
+ } catch (error) {
154
+ console.log('[Respectlytics] Failed to persist queue:', error);
155
+ }
156
+ }
157
+ async loadPersistedQueue() {
158
+ try {
159
+ const data = await _Storage.Storage.getItem(QUEUE_STORAGE_KEY);
160
+ if (data) {
161
+ const parsed = JSON.parse(data);
162
+ if (Array.isArray(parsed)) {
163
+ this.events = parsed;
164
+ console.log(`[Respectlytics] Loaded ${this.events.length} persisted event(s)`);
165
+ }
166
+ }
167
+ } catch (error) {
168
+ console.log('[Respectlytics] Failed to load persisted queue:', error);
169
+ this.events = [];
170
+ }
171
+ }
172
+ }
173
+ exports.EventQueue = EventQueue;
174
+ //# sourceMappingURL=EventQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","_netinfo","_interopRequireDefault","_Storage","e","__esModule","default","MAX_QUEUE_SIZE","FLUSH_INTERVAL_MS","QUEUE_STORAGE_KEY","EventQueue","events","isOnline","flushTimer","isFlushing","unsubscribeNetInfo","appStateSubscription","constructor","networkClient","start","loadPersistedQueue","setupNetworkMonitor","setupAppStateMonitor","scheduleFlush","console","log","stop","clearInterval","remove","add","event","push","persistQueue","length","flush","isConfigured","batch","send","error","getQueueSize","setInterval","NetInfo","addEventListener","state","wasOffline","isConnected","AppState","nextAppState","Storage","setItem","JSON","stringify","data","getItem","parsed","parse","Array","isArray","exports"],"sourceRoot":"../../src","sources":["EventQueue.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.networkClient = exports.NetworkError = exports.NetworkClient = void 0;
7
+ /**
8
+ * NetworkClient.ts
9
+ * Respectlytics React Native SDK
10
+ *
11
+ * Handles HTTP communication with the Respectlytics API.
12
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
13
+ */
14
+
15
+ const API_ENDPOINT = 'https://respectlytics.com/api/v1/events/';
16
+ const MAX_RETRIES = 3;
17
+ const TIMEOUT_MS = 30000;
18
+ let NetworkError = exports.NetworkError = /*#__PURE__*/function (NetworkError) {
19
+ NetworkError["NotConfigured"] = "NOT_CONFIGURED";
20
+ NetworkError["InvalidResponse"] = "INVALID_RESPONSE";
21
+ NetworkError["Unauthorized"] = "UNAUTHORIZED";
22
+ NetworkError["BadRequest"] = "BAD_REQUEST";
23
+ NetworkError["RateLimited"] = "RATE_LIMITED";
24
+ NetworkError["ServerError"] = "SERVER_ERROR";
25
+ NetworkError["NetworkError"] = "NETWORK_ERROR";
26
+ NetworkError["Timeout"] = "TIMEOUT";
27
+ return NetworkError;
28
+ }({});
29
+ class NetworkClient {
30
+ apiKey = null;
31
+
32
+ /**
33
+ * Configure the network client with an API key
34
+ */
35
+ configure(apiKey) {
36
+ this.apiKey = apiKey;
37
+ }
38
+
39
+ /**
40
+ * Check if the client is configured
41
+ */
42
+ isConfigured() {
43
+ return this.apiKey !== null;
44
+ }
45
+
46
+ /**
47
+ * Send events to the API
48
+ */
49
+ async send(events) {
50
+ if (!this.apiKey) {
51
+ throw new Error(NetworkError.NotConfigured);
52
+ }
53
+ for (const event of events) {
54
+ await this.sendEvent(event, 1);
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Send a single event with retry logic
60
+ */
61
+ async sendEvent(event, attempt) {
62
+ if (!this.apiKey) {
63
+ throw new Error(NetworkError.NotConfigured);
64
+ }
65
+ const controller = new AbortController();
66
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
67
+ try {
68
+ const response = await fetch(API_ENDPOINT, {
69
+ method: 'POST',
70
+ headers: {
71
+ 'Content-Type': 'application/json',
72
+ 'X-App-Key': this.apiKey
73
+ },
74
+ body: JSON.stringify(this.eventToPayload(event)),
75
+ signal: controller.signal
76
+ });
77
+ clearTimeout(timeoutId);
78
+ if (response.ok) {
79
+ return; // Success
80
+ }
81
+ switch (response.status) {
82
+ case 401:
83
+ throw new Error(NetworkError.Unauthorized);
84
+ case 400:
85
+ throw new Error(NetworkError.BadRequest);
86
+ case 429:
87
+ // Rate limited - retry with backoff
88
+ if (attempt < MAX_RETRIES) {
89
+ await this.delay(Math.pow(2, attempt) * 1000);
90
+ return this.sendEvent(event, attempt + 1);
91
+ }
92
+ throw new Error(NetworkError.RateLimited);
93
+ default:
94
+ if (response.status >= 500) {
95
+ // Server error - retry with backoff
96
+ if (attempt < MAX_RETRIES) {
97
+ await this.delay(Math.pow(2, attempt) * 1000);
98
+ return this.sendEvent(event, attempt + 1);
99
+ }
100
+ throw new Error(NetworkError.ServerError);
101
+ }
102
+ throw new Error(NetworkError.InvalidResponse);
103
+ }
104
+ } catch (error) {
105
+ clearTimeout(timeoutId);
106
+ if (error instanceof Error) {
107
+ // Don't retry auth or bad request errors
108
+ if (error.message === NetworkError.Unauthorized || error.message === NetworkError.BadRequest) {
109
+ throw error;
110
+ }
111
+
112
+ // Check for abort (timeout)
113
+ if (error.name === 'AbortError') {
114
+ if (attempt < MAX_RETRIES) {
115
+ await this.delay(Math.pow(2, attempt) * 1000);
116
+ return this.sendEvent(event, attempt + 1);
117
+ }
118
+ throw new Error(NetworkError.Timeout);
119
+ }
120
+ }
121
+
122
+ // Network error - retry with backoff
123
+ if (attempt < MAX_RETRIES) {
124
+ await this.delay(Math.pow(2, attempt) * 1000);
125
+ return this.sendEvent(event, attempt + 1);
126
+ }
127
+ throw new Error(NetworkError.NetworkError);
128
+ }
129
+ }
130
+
131
+ /**
132
+ * Convert Event object to API payload format
133
+ * Note: As of v2.0.0, no user_id field is sent (session-based analytics only)
134
+ */
135
+ eventToPayload(event) {
136
+ return {
137
+ event_name: event.eventName,
138
+ timestamp: event.timestamp,
139
+ session_id: event.sessionId,
140
+ screen: event.screen || undefined,
141
+ platform: event.platform,
142
+ os_version: event.osVersion,
143
+ app_version: event.appVersion,
144
+ locale: event.locale,
145
+ device_type: event.deviceType
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Helper to delay for exponential backoff
151
+ */
152
+ delay(ms) {
153
+ return new Promise(resolve => setTimeout(resolve, ms));
154
+ }
155
+ }
156
+ exports.NetworkClient = NetworkClient;
157
+ const networkClient = exports.networkClient = new NetworkClient();
158
+ //# sourceMappingURL=NetworkClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","exports","NetworkClient","apiKey","configure","isConfigured","send","events","Error","NotConfigured","event","sendEvent","attempt","controller","AbortController","timeoutId","setTimeout","abort","response","fetch","method","headers","body","JSON","stringify","eventToPayload","signal","clearTimeout","ok","status","Unauthorized","BadRequest","delay","Math","pow","RateLimited","ServerError","InvalidResponse","error","message","name","Timeout","event_name","eventName","timestamp","session_id","sessionId","screen","undefined","platform","os_version","osVersion","app_version","appVersion","locale","device_type","deviceType","ms","Promise","resolve","networkClient"],"sourceRoot":"../../src","sources":["NetworkClient.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,167 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.RespectlyticsSDK = void 0;
7
+ var _reactNative = require("react-native");
8
+ var _SessionManager = require("./SessionManager");
9
+ var _NetworkClient = require("./NetworkClient");
10
+ var _EventQueue = require("./EventQueue");
11
+ /**
12
+ * Respectlytics.ts
13
+ * Respectlytics React Native SDK
14
+ *
15
+ * Main entry point for the SDK.
16
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
17
+ */
18
+
19
+ /**
20
+ * Main entry point for the Respectlytics SDK.
21
+ *
22
+ * v2.0.0 uses session-based analytics only:
23
+ * - Session IDs are generated automatically in RAM
24
+ * - Sessions rotate every 2 hours
25
+ * - New session on every app restart
26
+ * - No persistent user tracking (GDPR/ePrivacy compliant)
27
+ *
28
+ * Usage:
29
+ * ```typescript
30
+ * // 1. Configure at app launch
31
+ * Respectlytics.configure('your-api-key');
32
+ *
33
+ * // 2. Track events
34
+ * Respectlytics.track('purchase');
35
+ * Respectlytics.track('view_product', 'ProductScreen');
36
+ * ```
37
+ */
38
+ class RespectlyticsSDK {
39
+ isConfigured = false;
40
+ constructor() {
41
+ this.networkClient = new _NetworkClient.NetworkClient();
42
+ this.eventQueue = new _EventQueue.EventQueue(this.networkClient);
43
+ this.sessionManager = new _SessionManager.SessionManager();
44
+ }
45
+
46
+ /**
47
+ * Initialize the SDK with your API key.
48
+ * Call once at app startup.
49
+ *
50
+ * @param apiKey Your Respectlytics API key from the dashboard
51
+ */
52
+ configure(apiKey) {
53
+ if (!apiKey || apiKey.trim() === '') {
54
+ console.log('[Respectlytics] ⚠️ API key cannot be empty');
55
+ return;
56
+ }
57
+ this.networkClient.configure(apiKey);
58
+ this.eventQueue.start();
59
+ this.isConfigured = true;
60
+ console.log('[Respectlytics] ✓ SDK configured');
61
+ }
62
+
63
+ /**
64
+ * Track an event with an optional screen name.
65
+ *
66
+ * The SDK automatically collects privacy-safe metadata:
67
+ * - timestamp, session_id, platform, os_version, app_version, locale
68
+ *
69
+ * @param eventName Name of the event (e.g., "purchase", "button_clicked")
70
+ * @param screen Optional screen name where the event occurred
71
+ */
72
+ track(eventName, screen) {
73
+ if (!this.isConfigured) {
74
+ console.log('[Respectlytics] ⚠️ SDK not configured. Call configure(apiKey) first.');
75
+ return;
76
+ }
77
+ if (!eventName || eventName.trim() === '') {
78
+ console.log('[Respectlytics] ⚠️ Event name cannot be empty');
79
+ return;
80
+ }
81
+ if (eventName.length > 100) {
82
+ console.log('[Respectlytics] ⚠️ Event name too long (max 100 characters)');
83
+ return;
84
+ }
85
+ const event = this.createEvent(eventName, screen);
86
+ this.eventQueue.add(event);
87
+ }
88
+
89
+ /**
90
+ * Force send all queued events immediately.
91
+ * Rarely needed - the SDK auto-flushes every 30 seconds or when the queue reaches 10 events.
92
+ */
93
+ async flush() {
94
+ await this.eventQueue.flush();
95
+ }
96
+
97
+ // MARK: - Private Helpers
98
+
99
+ createEvent(eventName, screen) {
100
+ const metadata = this.collectMetadata();
101
+ return {
102
+ eventName,
103
+ timestamp: new Date().toISOString(),
104
+ sessionId: this.sessionManager.getSessionId(),
105
+ screen: screen || null,
106
+ ...metadata
107
+ };
108
+ }
109
+ collectMetadata() {
110
+ // Determine platform
111
+ const platform = _reactNative.Platform.OS === 'ios' ? 'iOS' : 'Android';
112
+
113
+ // Get OS version
114
+ const osVersion = String(_reactNative.Platform.Version);
115
+
116
+ // Get app version - try to get from native modules
117
+ let appVersion = 'unknown';
118
+ try {
119
+ // React Native provides app info through different native modules
120
+ const {
121
+ PlatformConstants
122
+ } = _reactNative.NativeModules;
123
+ if (PlatformConstants?.reactNativeVersion) {
124
+ // This is React Native version, not app version
125
+ // App version should come from the host app
126
+ }
127
+ // For now, use 'unknown' as we can't reliably get app version without additional dependencies
128
+ // In a real app, the developer would configure this
129
+ } catch {
130
+ appVersion = 'unknown';
131
+ }
132
+
133
+ // Get locale
134
+ let locale = 'en_US';
135
+ try {
136
+ // React Native doesn't expose locale directly, but we can get it from platform
137
+ if (_reactNative.Platform.OS === 'ios') {
138
+ locale = _reactNative.NativeModules.SettingsManager?.settings?.AppleLocale || _reactNative.NativeModules.SettingsManager?.settings?.AppleLanguages?.[0] || 'en_US';
139
+ } else {
140
+ locale = _reactNative.NativeModules.I18nManager?.localeIdentifier || 'en_US';
141
+ }
142
+ } catch {
143
+ locale = 'en_US';
144
+ }
145
+
146
+ // Determine device type based on screen size
147
+ const {
148
+ width,
149
+ height
150
+ } = _reactNative.Dimensions.get('window');
151
+ const minDimension = Math.min(width, height);
152
+ const deviceType = minDimension >= 600 ? 'tablet' : 'phone';
153
+ return {
154
+ platform,
155
+ osVersion,
156
+ appVersion,
157
+ locale,
158
+ deviceType
159
+ };
160
+ }
161
+ }
162
+
163
+ // Export singleton instance
164
+ exports.RespectlyticsSDK = RespectlyticsSDK;
165
+ const Respectlytics = new RespectlyticsSDK();
166
+ var _default = exports.default = Respectlytics;
167
+ //# sourceMappingURL=Respectlytics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","_SessionManager","_NetworkClient","_EventQueue","RespectlyticsSDK","isConfigured","constructor","networkClient","NetworkClient","eventQueue","EventQueue","sessionManager","SessionManager","configure","apiKey","trim","console","log","start","track","eventName","screen","length","event","createEvent","add","flush","metadata","collectMetadata","timestamp","Date","toISOString","sessionId","getSessionId","platform","Platform","OS","osVersion","String","Version","appVersion","PlatformConstants","NativeModules","reactNativeVersion","locale","SettingsManager","settings","AppleLocale","AppleLanguages","I18nManager","localeIdentifier","width","height","Dimensions","get","minDimension","Math","min","deviceType","exports","Respectlytics","_default","default"],"sourceRoot":"../../src","sources":["Respectlytics.ts"],"mappings":"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","ignoreList":[]}