react-native-edgee 1.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 ADDED
@@ -0,0 +1,427 @@
1
+ # react-native-edgee
2
+
3
+ Lightweight Edgee data collection client for React Native with comprehensive native context collection.
4
+
5
+ ## ✨ Features
6
+
7
+ - **📱 Rich Native Context**: Automatically collects 30+ device & app data points
8
+ - **🔒 Privacy-First**: GDPR/CCPA compliant with optional device ID collection
9
+ - **📶 Offline Queue**: Events are persisted and retried when network is available
10
+ - **⚡ Lightweight**: Minimal impact on app size (~100KB total)
11
+ - **🎯 Type-Safe**: Full TypeScript support with comprehensive type definitions
12
+ - **📍 Auto Screen Tracking**: Optional helpers for Expo Router and React Navigation
13
+ - **🔄 Graceful Fallback**: Works without native modules (Expo Go compatible)
14
+
15
+ ## 📦 Installation
16
+
17
+ ### Step 1: Install Package & Dependencies
18
+
19
+ ```bash
20
+ # npm
21
+ npm install react-native-edgee @react-native-async-storage/async-storage @react-native-community/netinfo
22
+
23
+ # yarn
24
+ yarn add react-native-edgee @react-native-async-storage/async-storage @react-native-community/netinfo
25
+
26
+ # Expo
27
+ npx expo install react-native-edgee @react-native-async-storage/async-storage @react-native-community/netinfo
28
+ ```
29
+
30
+ ### Step 2: Platform Setup
31
+
32
+ Choose your platform setup:
33
+
34
+ <details>
35
+ <summary><strong>📱 React Native CLI (Full Native Context)</strong></summary>
36
+
37
+ **iOS:**
38
+ ```bash
39
+ cd ios && pod install && cd ..
40
+ ```
41
+
42
+ **Android:**
43
+
44
+ 1. **Add native module** to `android/app/src/main/java/.../MainApplication.java`:
45
+
46
+ ```java
47
+ import com.reactnativeedgee.EdgeeReactNativePackage;
48
+
49
+ public class MainApplication extends Application implements ReactApplication {
50
+ // ... existing code ...
51
+
52
+ @Override
53
+ protected List<ReactPackage> getPackages() {
54
+ @SuppressWarnings("UnnecessaryLocalVariable")
55
+ List<ReactPackage> packages = new PackageList(this).getPackages();
56
+
57
+ packages.add(new EdgeeReactNativePackage()); // 👈 Add this line
58
+
59
+ return packages;
60
+ }
61
+ }
62
+ ```
63
+
64
+ 2. **Add permission** to `android/app/src/main/AndroidManifest.xml`:
65
+
66
+ ```xml
67
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
68
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
69
+ <!-- Your existing manifest content -->
70
+ </manifest>
71
+ ```
72
+
73
+ 3. **Rebuild your app:**
74
+ ```bash
75
+ npx react-native run-android
76
+ ```
77
+
78
+ </details>
79
+
80
+ <details>
81
+ <summary><strong>⚡ Expo Development Build (Full Native Context)</strong></summary>
82
+
83
+ ```bash
84
+ # Install the package
85
+ npx expo install react-native-edgee @react-native-async-storage/async-storage @react-native-community/netinfo
86
+
87
+ # Create development build (this compiles native modules)
88
+ npx expo run:ios # For iOS
89
+ npx expo run:android # For Android
90
+ ```
91
+
92
+ **Note:** Native modules require a development build, not Expo Go.
93
+
94
+ </details>
95
+
96
+ <details>
97
+ <summary><strong>📱 Expo Go (JavaScript Context Only)</strong></summary>
98
+
99
+ ```bash
100
+ npx expo install react-native-edgee @react-native-async-storage/async-storage @react-native-community/netinfo
101
+ ```
102
+
103
+ **Limitations:** Native context collection is disabled. Only basic JavaScript context (screen size, platform, locale) will be available.
104
+
105
+ </details>
106
+
107
+ ### Step 3: Verify Installation
108
+
109
+ Test that native modules are working:
110
+
111
+ ```typescript
112
+ import { isNativeModuleAvailable } from 'react-native-edgee';
113
+
114
+ console.log('Native modules available:', isNativeModuleAvailable());
115
+ // Should log: true (React Native CLI, Expo Dev Build)
116
+ // Should log: false (Expo Go)
117
+ ```
118
+
119
+ ## 🚀 Quick Start
120
+
121
+ ### Basic Setup
122
+
123
+ ```typescript
124
+ import { EdgeeClient } from 'react-native-edgee';
125
+
126
+ // Create client instance
127
+ export const edgee = new EdgeeClient({
128
+ host: "https://your-edgee-host.com",
129
+ debug: __DEV__, // Enable debug logging in development
130
+ collectDeviceId: false, // Set to true if you need unique device tracking
131
+ });
132
+ ```
133
+
134
+ ### Track Events
135
+
136
+ ```typescript
137
+ // Track events (automatically includes rich native context)
138
+ // Consent is handled transparently - no need to check before each call!
139
+ edgee.track('App Launched', {
140
+ source: 'cold_start',
141
+ version: '1.0.0'
142
+ });
143
+
144
+ // Track user information
145
+ edgee.user({
146
+ id: '123',
147
+ email: 'user@example.com',
148
+ plan: 'premium'
149
+ });
150
+
151
+ // Track screen views
152
+ edgee.screen('Home Screen', {
153
+ category: 'main',
154
+ loaded_time: Date.now()
155
+ });
156
+ ```
157
+
158
+ ### Consent Management (Optional)
159
+
160
+ ```typescript
161
+ // Set consent - all tracking calls automatically respect this setting
162
+ await edgee.setConsent('granted'); // 'granted', 'denied', or 'pending'
163
+
164
+ // Check consent status
165
+ console.log('Current consent:', edgee.getConsent());
166
+ console.log('Can track:', edgee.canTrack());
167
+
168
+ // Listen for consent changes
169
+ const unsubscribe = edgee.onConsentChange((status) => {
170
+ console.log('Consent changed to:', status);
171
+ });
172
+
173
+ // Reset consent
174
+ await edgee.resetConsent();
175
+ ```
176
+
177
+ **Key Benefits:**
178
+ - 🔒 **Transparent**: No need to check consent before each tracking call
179
+ - 📡 **Auto-sync**: Consent events automatically sent to your Edgee server
180
+ - 💾 **Persistent**: Consent preference stored locally and remembered
181
+ - 🎯 **Compliant**: GDPR/CCPA ready with proper consent management
182
+
183
+ ## 📱 Rich Native Context
184
+
185
+ With native modules enabled, each event automatically includes comprehensive context:
186
+
187
+ ### App Information
188
+ - App name, version, build number
189
+ - Bundle/package identifier
190
+ - Installation and update timestamps
191
+
192
+ ### Device Information
193
+ - Device model, manufacturer, brand
194
+ - Screen dimensions, density, scale
195
+ - Hardware capabilities (tablet, simulator/emulator detection)
196
+
197
+ ### System Information
198
+ - OS name and version
199
+ - Locale, language, country, timezone
200
+ - Memory usage, storage info
201
+ - Battery level and state (iOS)
202
+
203
+ ### Network Information
204
+ - Connection type (WiFi, cellular, ethernet)
205
+ - Carrier name and network codes
206
+ - Radio technology (3G, 4G, 5G)
207
+
208
+ ### Privacy Information *(Optional)*
209
+ - Advertising ID (with proper consent on iOS 14+)
210
+ - Device ID (privacy-compliant, opt-in only)
211
+ - Tracking authorization status
212
+
213
+ ## ⚛️ React Integration
214
+
215
+ ### Context Provider (Optional)
216
+
217
+ ```typescript
218
+ import { EdgeeProvider, useEdgee } from 'react-native-edgee';
219
+
220
+ // Wrap your app
221
+ export default function App() {
222
+ return (
223
+ <EdgeeProvider host="https://your-edgee-host.com" debug={__DEV__}>
224
+ <YourApp />
225
+ </EdgeeProvider>
226
+ );
227
+ }
228
+
229
+ // Use in components
230
+ function SomeComponent() {
231
+ const edgee = useEdgee();
232
+
233
+ const handleButtonPress = () => {
234
+ // Tracking automatically respects consent - no need to check!
235
+ edgee.track('Button Pressed', { button_id: 'cta_main' });
236
+ };
237
+
238
+ const handleConsentGrant = async () => {
239
+ await edgee.setConsent('granted');
240
+ };
241
+
242
+ return (
243
+ <View>
244
+ <Button onPress={handleButtonPress} title="Track Me" />
245
+ <Button onPress={handleConsentGrant} title="Grant Consent" />
246
+ </View>
247
+ );
248
+ }
249
+ ```
250
+
251
+ ### Auto Screen Tracking
252
+
253
+ <details>
254
+ <summary><strong>Expo Router</strong></summary>
255
+
256
+ ```typescript
257
+ import { EdgeeAutoTracker } from 'react-native-edgee';
258
+
259
+ export default function RootLayout() {
260
+ return (
261
+ <>
262
+ <EdgeeAutoTracker edgee={edgee} />
263
+ <Stack>
264
+ <Stack.Screen name="index" />
265
+ <Stack.Screen name="profile" />
266
+ </Stack>
267
+ </>
268
+ );
269
+ }
270
+ ```
271
+
272
+ </details>
273
+
274
+ <details>
275
+ <summary><strong>React Navigation</strong></summary>
276
+
277
+ ```typescript
278
+ import { navigation } from 'react-native-edgee';
279
+
280
+ const navigationRef = useRef();
281
+
282
+ return (
283
+ <NavigationContainer
284
+ ref={navigationRef}
285
+ onStateChange={() => {
286
+ navigation.trackScreenChange(navigationRef, edgee);
287
+ }}
288
+ >
289
+ {/* Your navigation structure */}
290
+ </NavigationContainer>
291
+ );
292
+ ```
293
+
294
+ </details>
295
+
296
+ ## ⚙️ Configuration
297
+
298
+ ```typescript
299
+ interface EdgeeConfig {
300
+ host: string; // Your Edgee endpoint URL (required)
301
+ debug?: boolean; // Enable debug logging (default: false)
302
+ collectDeviceId?: boolean; // Collect unique device ID (default: false)
303
+ }
304
+ ```
305
+
306
+ ### Privacy Considerations
307
+
308
+ - **Device ID Collection**: Only enable `collectDeviceId: true` if you need persistent device tracking
309
+ - **iOS Advertising ID**: Automatically respects App Tracking Transparency (iOS 14+)
310
+ - **GDPR/CCPA Compliance**: All sensitive data collection is optional and clearly documented
311
+
312
+ ## 🔧 Advanced Usage
313
+
314
+ ### Manual Native Context Access
315
+
316
+ ```typescript
317
+ import { getNativeContext, isNativeModuleAvailable } from 'react-native-edgee';
318
+
319
+ // Check if native modules are available
320
+ if (isNativeModuleAvailable()) {
321
+ const context = await getNativeContext({ collectDeviceId: false });
322
+ console.log('Device model:', context.model);
323
+ console.log('Is tablet:', context.isTablet);
324
+ console.log('Network type:', context.networkType);
325
+ console.log('Total memory:', context.totalMemoryMB);
326
+ }
327
+ ```
328
+
329
+ ### Context Caching
330
+
331
+ ```typescript
332
+ import { clearContextCache } from 'react-native-edgee';
333
+
334
+ // Clear cached context (useful for testing or when context might change)
335
+ clearContextCache();
336
+ ```
337
+
338
+ ## 🔍 Troubleshooting
339
+
340
+ ### Common Issues
341
+
342
+ <details>
343
+ <summary><strong>"Module not found" Error</strong></summary>
344
+
345
+ **iOS:**
346
+ ```bash
347
+ cd ios && rm -rf build && pod install && cd ..
348
+ npx react-native run-ios
349
+ ```
350
+
351
+ **Android:**
352
+ - Ensure `EdgeeReactNativePackage` is added to `MainApplication.java`
353
+ - Clean build: `cd android && ./gradlew clean && cd ..`
354
+
355
+ </details>
356
+
357
+ <details>
358
+ <summary><strong>No Native Context in Events</strong></summary>
359
+
360
+ 1. Check if native modules are available:
361
+ ```typescript
362
+ console.log('Available:', isNativeModuleAvailable());
363
+ ```
364
+
365
+ 2. If `false`, verify platform setup above
366
+ 3. In Expo Go, this is expected (use Expo Development Build)
367
+
368
+ </details>
369
+
370
+ <details>
371
+ <summary><strong>Build Errors</strong></summary>
372
+
373
+ **Clean everything:**
374
+ ```bash
375
+ # React Native CLI
376
+ cd ios && rm -rf build && cd ..
377
+ cd android && ./gradlew clean && cd ..
378
+ npx react-native start --reset-cache
379
+
380
+ # Expo
381
+ npx expo run:ios --clear-cache
382
+ ```
383
+
384
+ </details>
385
+
386
+ ### Debug Mode
387
+
388
+ Enable debug logging to see what's happening:
389
+
390
+ ```typescript
391
+ const edgee = new EdgeeClient({
392
+ host: "https://your-edgee-host.com",
393
+ debug: true, // This will log all events and native context
394
+ });
395
+ ```
396
+
397
+ ## 📋 Compatibility
398
+
399
+ | Platform | Version | Native Context | Auto-Linking |
400
+ |----------|---------|----------------|--------------|
401
+ | **React Native** | 0.72+ | ✅ Full | iOS: ✅ Android: Manual |
402
+ | **iOS** | 11.0+ | ✅ Full | ✅ CocoaPods |
403
+ | **Android** | API 21+ | ✅ Full | ⚠️ Manual setup |
404
+ | **Expo Dev Build** | Latest | ✅ Full | ✅ Automatic |
405
+ | **Expo Go** | Latest | ⚠️ Fallback | N/A |
406
+
407
+ ## 📚 TypeScript Support
408
+
409
+ Full TypeScript support with comprehensive type definitions:
410
+
411
+ ```typescript
412
+ import type {
413
+ EdgeeNativeContext,
414
+ EdgeeClientContext,
415
+ EdgeeConfig
416
+ } from 'react-native-edgee';
417
+ ```
418
+
419
+ ## 📄 License
420
+
421
+ MIT
422
+
423
+ ## 🆘 Support
424
+
425
+ - **Issues**: [GitHub Issues](https://github.com/edgee-cloud/react-native-edgee/issues)
426
+ - **Documentation**: [Edgee Docs](https://docs.edgee.cloud)
427
+ - **Community**: [Edgee Discord](https://discord.gg/edgee)
@@ -0,0 +1,120 @@
1
+ buildscript {
2
+ repositories {
3
+ google()
4
+ mavenCentral()
5
+ }
6
+
7
+ dependencies {
8
+ classpath "com.android.tools.build:gradle:7.2.1"
9
+ }
10
+ }
11
+
12
+ apply plugin: "com.android.library"
13
+
14
+ def getExtOrDefault(name) {
15
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["ReactNativeEdgee_" + name]
16
+ }
17
+
18
+ def getExtOrIntegerDefault(name) {
19
+ return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["ReactNativeEdgee_" + name]).toInteger()
20
+ }
21
+
22
+ android {
23
+ compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
24
+
25
+ defaultConfig {
26
+ minSdkVersion getExtOrIntegerDefault("minSdkVersion")
27
+ targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
28
+ versionCode 1
29
+ versionName "1.0"
30
+ }
31
+
32
+ buildTypes {
33
+ release {
34
+ minifyEnabled false
35
+ }
36
+ }
37
+
38
+ lintOptions {
39
+ disable "GradleCompatible"
40
+ }
41
+
42
+ compileOptions {
43
+ sourceCompatibility JavaVersion.VERSION_1_8
44
+ targetCompatibility JavaVersion.VERSION_1_8
45
+ }
46
+ }
47
+
48
+ repositories {
49
+ mavenCentral()
50
+ google()
51
+
52
+ def found = false
53
+ def defaultDir = null
54
+ def androidSourcesName = "React Native sources"
55
+
56
+ if (rootProject.ext.has("reactNativeAndroidRoot")) {
57
+ defaultDir = rootProject.ext.get("reactNativeAndroidRoot")
58
+ } else {
59
+ defaultDir = new File(
60
+ projectDir,
61
+ "/../../../node_modules/react-native/android"
62
+ )
63
+ }
64
+
65
+ if (defaultDir.exists()) {
66
+ maven {
67
+ url defaultDir.toString()
68
+ name androidSourcesName
69
+ }
70
+
71
+ logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
72
+ found = true
73
+ } else {
74
+ def parentDir = rootProject.projectDir
75
+
76
+ 1.upto(5, {
77
+ if (found) return true
78
+ parentDir = parentDir.parentFile
79
+
80
+ def androidSourcesDir = new File(
81
+ parentDir,
82
+ "node_modules/react-native"
83
+ )
84
+
85
+ def androidPrebuiltBinaryDir = new File(
86
+ parentDir,
87
+ "node_modules/react-native/android"
88
+ )
89
+
90
+ if (androidPrebuiltBinaryDir.exists()) {
91
+ maven {
92
+ url androidPrebuiltBinaryDir.toString()
93
+ name androidSourcesName
94
+ }
95
+
96
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
97
+ found = true
98
+ } else if (androidSourcesDir.exists()) {
99
+ maven {
100
+ url androidSourcesDir.toString()
101
+ name androidSourcesName
102
+ }
103
+
104
+ logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
105
+ found = true
106
+ }
107
+ })
108
+ }
109
+
110
+ if (!found) {
111
+ throw new GradleException(
112
+ "${project.name}: unable to locate React Native android sources. " +
113
+ "Ensure you have you installed React Native as a dependency in your project and try again."
114
+ )
115
+ }
116
+ }
117
+
118
+ dependencies {
119
+ implementation "com.facebook.react:react-native:+"
120
+ }
@@ -0,0 +1,4 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+ package="com.reactnativeedgee">
3
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4
+ </manifest>