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
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.SessionManager = void 0;
7
+ /**
8
+ * SessionManager.ts
9
+ * Respectlytics React Native SDK
10
+ *
11
+ * Manages session ID generation and rotation.
12
+ * Sessions are stored in RAM only (never persisted) for GDPR/ePrivacy compliance.
13
+ * Sessions automatically rotate every 2 hours.
14
+ *
15
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
16
+ */
17
+
18
+ /**
19
+ * Generate a UUID v4 string
20
+ */
21
+ function generateUUID() {
22
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
23
+ const r = Math.random() * 16 | 0;
24
+ const v = c === 'x' ? r : r & 0x3 | 0x8;
25
+ return v.toString(16);
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Manages session ID generation and rotation.
31
+ *
32
+ * Session IDs are:
33
+ * - Generated immediately when the SDK initializes
34
+ * - Stored in RAM only (never persisted to AsyncStorage)
35
+ * - Rotated automatically every 2 hours
36
+ * - Regenerated on every app restart (new instance = new session)
37
+ *
38
+ * This RAM-only approach ensures GDPR/ePrivacy compliance:
39
+ * - No device storage = No consent required under ePrivacy Directive Article 5(3)
40
+ * - Each app launch creates a fresh, unlinked session
41
+ */
42
+ class SessionManager {
43
+ // Session ID generated immediately at class instantiation
44
+ sessionId = this.generateSessionId();
45
+ sessionStart = new Date();
46
+
47
+ // 2 hours in milliseconds
48
+ SESSION_TIMEOUT_MS = 2 * 60 * 60 * 1000;
49
+
50
+ /**
51
+ * Get current session ID, rotating if necessary.
52
+ * Session rotates after 2 hours of continuous use.
53
+ */
54
+ getSessionId() {
55
+ const now = new Date();
56
+ const elapsed = now.getTime() - this.sessionStart.getTime();
57
+
58
+ // Rotate session after 2 hours
59
+ if (elapsed > this.SESSION_TIMEOUT_MS) {
60
+ this.sessionId = this.generateSessionId();
61
+ this.sessionStart = now;
62
+ }
63
+ return this.sessionId;
64
+ }
65
+
66
+ /**
67
+ * Generate a new session ID (32 lowercase hex characters)
68
+ * UUID without dashes, all lowercase
69
+ */
70
+ generateSessionId() {
71
+ return generateUUID().toLowerCase().replace(/-/g, '');
72
+ }
73
+ }
74
+ exports.SessionManager = SessionManager;
75
+ //# sourceMappingURL=SessionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["generateUUID","replace","c","r","Math","random","v","toString","SessionManager","sessionId","generateSessionId","sessionStart","Date","SESSION_TIMEOUT_MS","getSessionId","now","elapsed","getTime","toLowerCase","exports"],"sourceRoot":"../../src","sources":["SessionManager.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,SAASA,YAAYA,CAAA,EAAW;EAC9B,OAAO,sCAAsC,CAACC,OAAO,CAAC,OAAO,EAAGC,CAAC,IAAK;IACpE,MAAMC,CAAC,GAAIC,IAAI,CAACC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAI,CAAC;IAClC,MAAMC,CAAC,GAAGJ,CAAC,KAAK,GAAG,GAAGC,CAAC,GAAIA,CAAC,GAAG,GAAG,GAAI,GAAG;IACzC,OAAOG,CAAC,CAACC,QAAQ,CAAC,EAAE,CAAC;EACvB,CAAC,CAAC;AACJ;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMC,cAAc,CAAC;EAC1B;EACQC,SAAS,GAAW,IAAI,CAACC,iBAAiB,CAAC,CAAC;EAC5CC,YAAY,GAAS,IAAIC,IAAI,CAAC,CAAC;;EAEvC;EACiBC,kBAAkB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI;;EAExD;AACF;AACA;AACA;EACEC,YAAYA,CAAA,EAAW;IACrB,MAAMC,GAAG,GAAG,IAAIH,IAAI,CAAC,CAAC;IACtB,MAAMI,OAAO,GAAGD,GAAG,CAACE,OAAO,CAAC,CAAC,GAAG,IAAI,CAACN,YAAY,CAACM,OAAO,CAAC,CAAC;;IAE3D;IACA,IAAID,OAAO,GAAG,IAAI,CAACH,kBAAkB,EAAE;MACrC,IAAI,CAACJ,SAAS,GAAG,IAAI,CAACC,iBAAiB,CAAC,CAAC;MACzC,IAAI,CAACC,YAAY,GAAGI,GAAG;IACzB;IAEA,OAAO,IAAI,CAACN,SAAS;EACvB;;EAEA;AACF;AACA;AACA;EACUC,iBAAiBA,CAAA,EAAW;IAClC,OAAOV,YAAY,CAAC,CAAC,CAACkB,WAAW,CAAC,CAAC,CAACjB,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC;EACvD;AACF;AAACkB,OAAA,CAAAX,cAAA,GAAAA,cAAA","ignoreList":[]}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Storage = void 0;
7
+ var _asyncStorage = _interopRequireDefault(require("@react-native-async-storage/async-storage"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ /**
10
+ * Storage.ts
11
+ * Respectlytics React Native SDK
12
+ *
13
+ * Wrapper around AsyncStorage for persisting SDK data.
14
+ *
15
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
16
+ */
17
+
18
+ /**
19
+ * Storage wrapper providing typed access to AsyncStorage
20
+ */
21
+ class Storage {
22
+ /**
23
+ * Get a string value from storage
24
+ */
25
+ static async getItem(key) {
26
+ try {
27
+ return await _asyncStorage.default.getItem(key);
28
+ } catch (error) {
29
+ console.log(`[Respectlytics] Failed to read from storage: ${key}`);
30
+ return null;
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Set a string value in storage
36
+ */
37
+ static async setItem(key, value) {
38
+ try {
39
+ await _asyncStorage.default.setItem(key, value);
40
+ } catch (error) {
41
+ console.log(`[Respectlytics] Failed to write to storage: ${key}`);
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Remove a value from storage
47
+ */
48
+ static async removeItem(key) {
49
+ try {
50
+ await _asyncStorage.default.removeItem(key);
51
+ } catch (error) {
52
+ console.log(`[Respectlytics] Failed to remove from storage: ${key}`);
53
+ }
54
+ }
55
+ }
56
+ exports.Storage = Storage;
57
+ //# sourceMappingURL=Storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_asyncStorage","_interopRequireDefault","require","e","__esModule","default","Storage","getItem","key","AsyncStorage","error","console","log","setItem","value","removeItem","exports"],"sourceRoot":"../../src","sources":["Storage.ts"],"mappings":";;;;;;AASA,IAAAA,aAAA,GAAAC,sBAAA,CAAAC,OAAA;AAAqE,SAAAD,uBAAAE,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AATrE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAIA;AACA;AACA;AACO,MAAMG,OAAO,CAAC;EACnB;AACF;AACA;EACE,aAAaC,OAAOA,CAACC,GAAW,EAA0B;IACxD,IAAI;MACF,OAAO,MAAMC,qBAAY,CAACF,OAAO,CAACC,GAAG,CAAC;IACxC,CAAC,CAAC,OAAOE,KAAK,EAAE;MACdC,OAAO,CAACC,GAAG,CAAC,gDAAgDJ,GAAG,EAAE,CAAC;MAClE,OAAO,IAAI;IACb;EACF;;EAEA;AACF;AACA;EACE,aAAaK,OAAOA,CAACL,GAAW,EAAEM,KAAa,EAAiB;IAC9D,IAAI;MACF,MAAML,qBAAY,CAACI,OAAO,CAACL,GAAG,EAAEM,KAAK,CAAC;IACxC,CAAC,CAAC,OAAOJ,KAAK,EAAE;MACdC,OAAO,CAACC,GAAG,CAAC,+CAA+CJ,GAAG,EAAE,CAAC;IACnE;EACF;;EAEA;AACF;AACA;EACE,aAAaO,UAAUA,CAACP,GAAW,EAAiB;IAClD,IAAI;MACF,MAAMC,qBAAY,CAACM,UAAU,CAACP,GAAG,CAAC;IACpC,CAAC,CAAC,OAAOE,KAAK,EAAE;MACdC,OAAO,CAACC,GAAG,CAAC,kDAAkDJ,GAAG,EAAE,CAAC;IACtE;EACF;AACF;AAACQ,OAAA,CAAAV,OAAA,GAAAA,OAAA","ignoreList":[]}
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "Event", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _types.Event;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "RespectlyticsSDK", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _Respectlytics.RespectlyticsSDK;
16
+ }
17
+ });
18
+ exports.default = void 0;
19
+ var _Respectlytics = _interopRequireWildcard(require("./Respectlytics"));
20
+ var _types = require("./types");
21
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
22
+ /**
23
+ * Respectlytics React Native SDK
24
+ *
25
+ * Official SDK for privacy-first, session-based analytics.
26
+ *
27
+ * v2.0.0 Features:
28
+ * - Session-based analytics (no persistent user tracking)
29
+ * - RAM-only session storage (GDPR/ePrivacy compliant)
30
+ * - Automatic 2-hour session rotation
31
+ * - New session on every app restart
32
+ *
33
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
34
+ */
35
+ // Default export - the main SDK instance
36
+ var _default = exports.default = _Respectlytics.default; // Named exports for advanced usage
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_Respectlytics","_interopRequireWildcard","require","_types","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","_default","exports","Respectlytics"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;AAcA,IAAAA,cAAA,GAAAC,uBAAA,CAAAC,OAAA;AAOA,IAAAC,MAAA,GAAAD,OAAA;AAAgC,SAAAD,wBAAAG,CAAA,EAAAC,CAAA,6BAAAC,OAAA,MAAAC,CAAA,OAAAD,OAAA,IAAAE,CAAA,OAAAF,OAAA,YAAAL,uBAAA,YAAAA,CAAAG,CAAA,EAAAC,CAAA,SAAAA,CAAA,IAAAD,CAAA,IAAAA,CAAA,CAAAK,UAAA,SAAAL,CAAA,MAAAM,CAAA,EAAAC,CAAA,EAAAC,CAAA,KAAAC,SAAA,QAAAC,OAAA,EAAAV,CAAA,iBAAAA,CAAA,uBAAAA,CAAA,yBAAAA,CAAA,SAAAQ,CAAA,MAAAF,CAAA,GAAAL,CAAA,GAAAG,CAAA,GAAAD,CAAA,QAAAG,CAAA,CAAAK,GAAA,CAAAX,CAAA,UAAAM,CAAA,CAAAM,GAAA,CAAAZ,CAAA,GAAAM,CAAA,CAAAO,GAAA,CAAAb,CAAA,EAAAQ,CAAA,gBAAAP,CAAA,IAAAD,CAAA,gBAAAC,CAAA,OAAAa,cAAA,CAAAC,IAAA,CAAAf,CAAA,EAAAC,CAAA,OAAAM,CAAA,IAAAD,CAAA,GAAAU,MAAA,CAAAC,cAAA,KAAAD,MAAA,CAAAE,wBAAA,CAAAlB,CAAA,EAAAC,CAAA,OAAAM,CAAA,CAAAK,GAAA,IAAAL,CAAA,CAAAM,GAAA,IAAAP,CAAA,CAAAE,CAAA,EAAAP,CAAA,EAAAM,CAAA,IAAAC,CAAA,CAAAP,CAAA,IAAAD,CAAA,CAAAC,CAAA,WAAAO,CAAA,KAAAR,CAAA,EAAAC,CAAA;AArBhC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAIA;AAAA,IAAAkB,QAAA,GAAAC,OAAA,CAAAV,OAAA,GACeW,sBAAa,EAE5B","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.STORAGE_KEYS = void 0;
7
+ /**
8
+ * types.ts
9
+ * Respectlytics React Native SDK
10
+ *
11
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
12
+ * This SDK is provided under a proprietary license.
13
+ * See LICENSE file for details.
14
+ */
15
+
16
+ /**
17
+ * Represents an analytics event - flat structure matching API payload
18
+ *
19
+ * This interface only contains fields accepted by the Respectlytics API.
20
+ * The API uses a strict allowlist for privacy protection.
21
+ * Custom properties are NOT supported - this is by design for privacy.
22
+ *
23
+ * Note: As of v2.0.0, there is no userId field. Session-based analytics only.
24
+ */
25
+
26
+ /**
27
+ * Storage keys used by the SDK
28
+ *
29
+ * Note: As of v2.0.0, we only persist the event queue.
30
+ * Session IDs are RAM-only for GDPR/ePrivacy compliance.
31
+ */
32
+ const STORAGE_KEYS = exports.STORAGE_KEYS = {
33
+ EVENT_QUEUE: 'com.respectlytics.eventQueue'
34
+ };
35
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["STORAGE_KEYS","exports","EVENT_QUEUE"],"sourceRoot":"../../src","sources":["types.ts"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAaA;AACA;AACA;AACA;AACA;AACA;AACO,MAAMA,YAAY,GAAAC,OAAA,CAAAD,YAAA,GAAG;EAC1BE,WAAW,EAAE;AACf,CAAU","ignoreList":[]}
@@ -0,0 +1,166 @@
1
+ /**
2
+ * EventQueue.ts
3
+ * Respectlytics React Native SDK
4
+ *
5
+ * Manages event batching, persistence, and automatic flushing.
6
+ * Events are NEVER lost - they are persisted immediately and retried on failure.
7
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
8
+ */
9
+
10
+ import { AppState } from 'react-native';
11
+ import NetInfo from '@react-native-community/netinfo';
12
+ import { Storage } from './Storage';
13
+ const MAX_QUEUE_SIZE = 10;
14
+ const FLUSH_INTERVAL_MS = 30000; // 30 seconds
15
+ const QUEUE_STORAGE_KEY = 'com.respectlytics.eventQueue';
16
+ export class EventQueue {
17
+ events = [];
18
+ isOnline = true;
19
+ flushTimer = null;
20
+ isFlushing = false;
21
+ unsubscribeNetInfo = null;
22
+ appStateSubscription = null;
23
+ constructor(networkClient) {
24
+ this.networkClient = networkClient;
25
+ }
26
+
27
+ /**
28
+ * Initialize the queue - load persisted events and set up listeners
29
+ */
30
+ async start() {
31
+ await this.loadPersistedQueue();
32
+ this.setupNetworkMonitor();
33
+ this.setupAppStateMonitor();
34
+ this.scheduleFlush();
35
+ console.log('[Respectlytics] ✓ Event queue started');
36
+ }
37
+
38
+ /**
39
+ * Stop the queue and clean up resources
40
+ */
41
+ stop() {
42
+ if (this.flushTimer) {
43
+ clearInterval(this.flushTimer);
44
+ this.flushTimer = null;
45
+ }
46
+ if (this.unsubscribeNetInfo) {
47
+ this.unsubscribeNetInfo();
48
+ this.unsubscribeNetInfo = null;
49
+ }
50
+ if (this.appStateSubscription) {
51
+ this.appStateSubscription.remove();
52
+ this.appStateSubscription = null;
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Add an event to the queue
58
+ * CRITICAL: Events are persisted IMMEDIATELY before any async operations
59
+ */
60
+ async add(event) {
61
+ this.events.push(event);
62
+
63
+ // IMMEDIATELY persist before any async operations
64
+ await this.persistQueue();
65
+
66
+ // Check if we should flush
67
+ if (this.events.length >= MAX_QUEUE_SIZE) {
68
+ this.flush();
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Force flush all queued events
74
+ */
75
+ async flush() {
76
+ if (this.isFlushing || this.events.length === 0) {
77
+ return;
78
+ }
79
+ if (!this.isOnline) {
80
+ console.log('[Respectlytics] Offline, skipping flush');
81
+ return;
82
+ }
83
+ if (!this.networkClient.isConfigured()) {
84
+ console.log('[Respectlytics] ⚠️ SDK not configured, skipping flush');
85
+ return;
86
+ }
87
+ this.isFlushing = true;
88
+
89
+ // Take a snapshot of events to send
90
+ const batch = [...this.events];
91
+ this.events = [];
92
+ await this.persistQueue();
93
+ try {
94
+ await this.networkClient.send(batch);
95
+ console.log(`[Respectlytics] ✓ Sent ${batch.length} event(s)`);
96
+ } catch (error) {
97
+ // Re-add failed events to the front of the queue
98
+ this.events = [...batch, ...this.events];
99
+ await this.persistQueue();
100
+ console.log('[Respectlytics] Failed to send events, will retry later');
101
+ } finally {
102
+ this.isFlushing = false;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Get current queue size (for testing)
108
+ */
109
+ getQueueSize() {
110
+ return this.events.length;
111
+ }
112
+
113
+ // MARK: - Private Helpers
114
+
115
+ scheduleFlush() {
116
+ if (this.flushTimer) {
117
+ clearInterval(this.flushTimer);
118
+ }
119
+ this.flushTimer = setInterval(() => {
120
+ this.flush();
121
+ }, FLUSH_INTERVAL_MS);
122
+ }
123
+ setupNetworkMonitor() {
124
+ this.unsubscribeNetInfo = NetInfo.addEventListener(state => {
125
+ const wasOffline = !this.isOnline;
126
+ this.isOnline = state.isConnected ?? false;
127
+
128
+ // If we just came online, try to flush
129
+ if (wasOffline && this.isOnline) {
130
+ console.log('[Respectlytics] Network restored, flushing queue');
131
+ this.flush();
132
+ }
133
+ });
134
+ }
135
+ setupAppStateMonitor() {
136
+ this.appStateSubscription = AppState.addEventListener('change', nextAppState => {
137
+ // Flush when app goes to background
138
+ if (nextAppState === 'background' || nextAppState === 'inactive') {
139
+ this.flush();
140
+ }
141
+ });
142
+ }
143
+ async persistQueue() {
144
+ try {
145
+ await Storage.setItem(QUEUE_STORAGE_KEY, JSON.stringify(this.events));
146
+ } catch (error) {
147
+ console.log('[Respectlytics] Failed to persist queue:', error);
148
+ }
149
+ }
150
+ async loadPersistedQueue() {
151
+ try {
152
+ const data = await Storage.getItem(QUEUE_STORAGE_KEY);
153
+ if (data) {
154
+ const parsed = JSON.parse(data);
155
+ if (Array.isArray(parsed)) {
156
+ this.events = parsed;
157
+ console.log(`[Respectlytics] Loaded ${this.events.length} persisted event(s)`);
158
+ }
159
+ }
160
+ } catch (error) {
161
+ console.log('[Respectlytics] Failed to load persisted queue:', error);
162
+ this.events = [];
163
+ }
164
+ }
165
+ }
166
+ //# sourceMappingURL=EventQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["AppState","NetInfo","Storage","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","addEventListener","state","wasOffline","isConnected","nextAppState","setItem","JSON","stringify","data","getItem","parsed","parse","Array","isArray"],"sourceRoot":"../../src","sources":["EventQueue.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * NetworkClient.ts
3
+ * Respectlytics React Native SDK
4
+ *
5
+ * Handles HTTP communication with the Respectlytics API.
6
+ * Copyright (c) 2025 Respectlytics. All rights reserved.
7
+ */
8
+
9
+ const API_ENDPOINT = 'https://respectlytics.com/api/v1/events/';
10
+ const MAX_RETRIES = 3;
11
+ const TIMEOUT_MS = 30000;
12
+ export let NetworkError = /*#__PURE__*/function (NetworkError) {
13
+ NetworkError["NotConfigured"] = "NOT_CONFIGURED";
14
+ NetworkError["InvalidResponse"] = "INVALID_RESPONSE";
15
+ NetworkError["Unauthorized"] = "UNAUTHORIZED";
16
+ NetworkError["BadRequest"] = "BAD_REQUEST";
17
+ NetworkError["RateLimited"] = "RATE_LIMITED";
18
+ NetworkError["ServerError"] = "SERVER_ERROR";
19
+ NetworkError["NetworkError"] = "NETWORK_ERROR";
20
+ NetworkError["Timeout"] = "TIMEOUT";
21
+ return NetworkError;
22
+ }({});
23
+ export class NetworkClient {
24
+ apiKey = null;
25
+
26
+ /**
27
+ * Configure the network client with an API key
28
+ */
29
+ configure(apiKey) {
30
+ this.apiKey = apiKey;
31
+ }
32
+
33
+ /**
34
+ * Check if the client is configured
35
+ */
36
+ isConfigured() {
37
+ return this.apiKey !== null;
38
+ }
39
+
40
+ /**
41
+ * Send events to the API
42
+ */
43
+ async send(events) {
44
+ if (!this.apiKey) {
45
+ throw new Error(NetworkError.NotConfigured);
46
+ }
47
+ for (const event of events) {
48
+ await this.sendEvent(event, 1);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Send a single event with retry logic
54
+ */
55
+ async sendEvent(event, attempt) {
56
+ if (!this.apiKey) {
57
+ throw new Error(NetworkError.NotConfigured);
58
+ }
59
+ const controller = new AbortController();
60
+ const timeoutId = setTimeout(() => controller.abort(), TIMEOUT_MS);
61
+ try {
62
+ const response = await fetch(API_ENDPOINT, {
63
+ method: 'POST',
64
+ headers: {
65
+ 'Content-Type': 'application/json',
66
+ 'X-App-Key': this.apiKey
67
+ },
68
+ body: JSON.stringify(this.eventToPayload(event)),
69
+ signal: controller.signal
70
+ });
71
+ clearTimeout(timeoutId);
72
+ if (response.ok) {
73
+ return; // Success
74
+ }
75
+ switch (response.status) {
76
+ case 401:
77
+ throw new Error(NetworkError.Unauthorized);
78
+ case 400:
79
+ throw new Error(NetworkError.BadRequest);
80
+ case 429:
81
+ // Rate limited - retry with backoff
82
+ if (attempt < MAX_RETRIES) {
83
+ await this.delay(Math.pow(2, attempt) * 1000);
84
+ return this.sendEvent(event, attempt + 1);
85
+ }
86
+ throw new Error(NetworkError.RateLimited);
87
+ default:
88
+ if (response.status >= 500) {
89
+ // Server error - retry with backoff
90
+ if (attempt < MAX_RETRIES) {
91
+ await this.delay(Math.pow(2, attempt) * 1000);
92
+ return this.sendEvent(event, attempt + 1);
93
+ }
94
+ throw new Error(NetworkError.ServerError);
95
+ }
96
+ throw new Error(NetworkError.InvalidResponse);
97
+ }
98
+ } catch (error) {
99
+ clearTimeout(timeoutId);
100
+ if (error instanceof Error) {
101
+ // Don't retry auth or bad request errors
102
+ if (error.message === NetworkError.Unauthorized || error.message === NetworkError.BadRequest) {
103
+ throw error;
104
+ }
105
+
106
+ // Check for abort (timeout)
107
+ if (error.name === 'AbortError') {
108
+ if (attempt < MAX_RETRIES) {
109
+ await this.delay(Math.pow(2, attempt) * 1000);
110
+ return this.sendEvent(event, attempt + 1);
111
+ }
112
+ throw new Error(NetworkError.Timeout);
113
+ }
114
+ }
115
+
116
+ // Network error - retry with backoff
117
+ if (attempt < MAX_RETRIES) {
118
+ await this.delay(Math.pow(2, attempt) * 1000);
119
+ return this.sendEvent(event, attempt + 1);
120
+ }
121
+ throw new Error(NetworkError.NetworkError);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Convert Event object to API payload format
127
+ * Note: As of v2.0.0, no user_id field is sent (session-based analytics only)
128
+ */
129
+ eventToPayload(event) {
130
+ return {
131
+ event_name: event.eventName,
132
+ timestamp: event.timestamp,
133
+ session_id: event.sessionId,
134
+ screen: event.screen || undefined,
135
+ platform: event.platform,
136
+ os_version: event.osVersion,
137
+ app_version: event.appVersion,
138
+ locale: event.locale,
139
+ device_type: event.deviceType
140
+ };
141
+ }
142
+
143
+ /**
144
+ * Helper to delay for exponential backoff
145
+ */
146
+ delay(ms) {
147
+ return new Promise(resolve => setTimeout(resolve, ms));
148
+ }
149
+ }
150
+ export const networkClient = new NetworkClient();
151
+ //# sourceMappingURL=NetworkClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["API_ENDPOINT","MAX_RETRIES","TIMEOUT_MS","NetworkError","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":[]}