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.
- package/README.md +43 -34
- package/lib/commonjs/EventQueue.js +174 -0
- package/lib/commonjs/EventQueue.js.map +1 -0
- package/lib/commonjs/NetworkClient.js +158 -0
- package/lib/commonjs/NetworkClient.js.map +1 -0
- package/lib/commonjs/Respectlytics.js +167 -0
- package/lib/commonjs/Respectlytics.js.map +1 -0
- package/lib/commonjs/SessionManager.js +75 -0
- package/lib/commonjs/SessionManager.js.map +1 -0
- package/lib/commonjs/Storage.js +57 -0
- package/lib/commonjs/Storage.js.map +1 -0
- package/lib/commonjs/index.js +37 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/types.js +35 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/EventQueue.js +166 -0
- package/lib/module/EventQueue.js.map +1 -0
- package/lib/module/NetworkClient.js +151 -0
- package/lib/module/NetworkClient.js.map +1 -0
- package/lib/module/Respectlytics.js +162 -0
- package/lib/module/Respectlytics.js.map +1 -0
- package/lib/module/SessionManager.js +68 -0
- package/lib/module/SessionManager.js.map +1 -0
- package/lib/module/Storage.js +50 -0
- package/lib/module/Storage.js.map +1 -0
- package/lib/module/index.js +23 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/types.js +29 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/EventQueue.d.ts +47 -0
- package/lib/typescript/EventQueue.d.ts.map +1 -0
- package/lib/typescript/NetworkClient.d.ts +48 -0
- package/lib/typescript/NetworkClient.d.ts.map +1 -0
- package/lib/typescript/Respectlytics.d.ts +61 -0
- package/lib/typescript/Respectlytics.d.ts.map +1 -0
- package/lib/typescript/SessionManager.d.ts +39 -0
- package/lib/typescript/SessionManager.d.ts.map +1 -0
- package/lib/typescript/Storage.d.ts +26 -0
- package/lib/typescript/Storage.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +18 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +38 -0
- package/lib/typescript/types.d.ts.map +1 -0
- package/package.json +2 -2
- package/src/NetworkClient.ts +1 -1
- package/src/Respectlytics.ts +7 -29
- package/src/SessionManager.ts +24 -20
- package/src/index.ts +8 -1
- package/src/types.ts +5 -2
- 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":[]}
|