@magicpixel/rn-mp-client-sdk 1.13.22 → 1.13.23

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 CHANGED
@@ -14,16 +14,55 @@ npm install @magicpixel/rn-mp-client-sdk
14
14
  npm install react-native @react-native-async-storage/async-storage
15
15
  ```
16
16
 
17
- ### For Bare React Native (Optional)
17
+ ### For Bare React Native
18
18
 
19
- For enhanced device info detection:
19
+ Bare React Native apps require additional setup:
20
20
 
21
+ #### 1. Install Required Dependencies
22
+
23
+ ```sh
24
+ npm install react-native-get-random-values react-native-device-info
25
+ ```
26
+
27
+ #### 2. Link Native Modules (Required)
28
+
29
+ **iOS:**
21
30
  ```sh
22
- npm install react-native-device-info
23
- npx pod-install
31
+ cd ios && pod install && cd ..
32
+ ```
33
+
34
+ **Android:** Native modules are auto-linked via Gradle.
35
+
36
+ > ⚠️ **Important:** After running `pod install`, you must fully restart the app:
37
+ > 1. Kill the app in the simulator/device
38
+ > 2. Stop Metro bundler (`Ctrl+C`)
39
+ > 3. Restart Metro (`npx react-native start`)
40
+ > 4. Rebuild and launch the app
41
+ >
42
+ > Simply reloading Metro is not sufficient - the native binary must be rebuilt.
43
+
44
+ #### 3. Add Polyfill Import (Required)
45
+
46
+ Add this import at the very top of your app's entry file (`index.js`), **before any other imports**:
47
+
48
+ ```javascript
49
+ import 'react-native-get-random-values'; // Must be first import!
50
+
51
+ import {AppRegistry} from 'react-native';
52
+ import App from './App';
53
+ import {name as appName} from './app.json';
54
+
55
+ AppRegistry.registerComponent(appName, () => App);
24
56
  ```
25
57
 
26
- > **Note**: For Expo apps, device info is automatically detected using Expo modules. No additional setup required.
58
+ > ⚠️ **Without this setup, you will see the error:**
59
+ > ```
60
+ > MagicPixel SDK initialization failed: Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'RNGetRandomValues' could not be found.
61
+ > ```
62
+
63
+ The SDK uses ULID for generating unique identifiers, which requires `crypto.getRandomValues()`. This polyfill must be loaded before any other code runs.
64
+
65
+ > **Note**: For Expo managed apps, no additional setup is required - the polyfill is handled automatically.
27
66
 
28
67
  ## Quick Start
29
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magicpixel/rn-mp-client-sdk",
3
- "version": "1.13.22",
3
+ "version": "1.13.23",
4
4
  "description": "React Native SDK for MagicPixel analytics and tag management",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -10,6 +10,7 @@
10
10
  "files": [
11
11
  "src",
12
12
  "lib",
13
+ "scripts",
13
14
  "!lib/typescript/example",
14
15
  "!**/__tests__",
15
16
  "!**/__fixtures__",
@@ -20,6 +21,7 @@
20
21
  "typescript": "tsc --noEmit",
21
22
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
22
23
  "prepare": "bob build",
24
+ "postinstall": "node scripts/postinstall.js",
23
25
  "release": "release-it",
24
26
  "example": "yarn --cwd example",
25
27
  "bootstrap": "yarn example && yarn && yarn example pods",
@@ -91,7 +93,13 @@
91
93
  },
92
94
  "peerDependencies": {
93
95
  "react": "*",
94
- "react-native": "*"
96
+ "react-native": "*",
97
+ "react-native-get-random-values": ">=1.8.0"
98
+ },
99
+ "peerDependenciesMeta": {
100
+ "react-native-get-random-values": {
101
+ "optional": true
102
+ }
95
103
  },
96
104
  "commitlint": {
97
105
  "extends": [
@@ -0,0 +1,29 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const child_process = require('child_process');
4
+
5
+ const root = path.resolve(__dirname, '..');
6
+ const args = process.argv.slice(2);
7
+ const options = {
8
+ cwd: process.cwd(),
9
+ env: process.env,
10
+ stdio: 'inherit',
11
+ encoding: 'utf-8',
12
+ };
13
+
14
+ if (os.type() === 'Windows_NT') {
15
+ options.shell = true;
16
+ }
17
+
18
+ let result;
19
+
20
+ if (process.cwd() !== root || args.length) {
21
+ // We're not in the root of the project, or additional arguments were passed
22
+ // In this case, forward the command to `yarn`
23
+ result = child_process.spawnSync('yarn', args, options);
24
+ } else {
25
+ // If `yarn` is run without arguments, perform bootstrap
26
+ result = child_process.spawnSync('yarn', ['bootstrap'], options);
27
+ }
28
+
29
+ process.exitCode = result.status;
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MagicPixel SDK Postinstall Script
5
+ * Detects bare React Native projects and displays setup instructions
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+
11
+ // ANSI color codes
12
+ const colors = {
13
+ reset: '\x1b[0m',
14
+ bright: '\x1b[1m',
15
+ dim: '\x1b[2m',
16
+ yellow: '\x1b[33m',
17
+ cyan: '\x1b[36m',
18
+ white: '\x1b[37m',
19
+ bgMagenta: '\x1b[45m',
20
+ bgBlue: '\x1b[44m',
21
+ };
22
+
23
+ function getAppRoot() {
24
+ // Navigate up from node_modules/@magicpixel/rn-mp-client-sdk/scripts
25
+ // Structure: <app>/node_modules/@magicpixel/rn-mp-client-sdk/scripts/postinstall.js
26
+ // Or with yalc: <app>/.yalc/@magicpixel/rn-mp-client-sdk/scripts/postinstall.js
27
+ let current = __dirname;
28
+
29
+ for (let i = 0; i < 10; i++) {
30
+ current = path.dirname(current);
31
+ const packageJsonPath = path.join(current, 'package.json');
32
+
33
+ if (fs.existsSync(packageJsonPath)) {
34
+ try {
35
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
36
+ // Skip our own package.json
37
+ if (pkg.name === '@magicpixel/rn-mp-client-sdk') {
38
+ continue;
39
+ }
40
+ // Found the host app
41
+ return current;
42
+ } catch (e) {
43
+ // Continue searching
44
+ }
45
+ }
46
+ }
47
+ return null;
48
+ }
49
+
50
+ function detectProjectType(appRoot) {
51
+ if (!appRoot) return 'unknown';
52
+
53
+ const hasIosFolder = fs.existsSync(path.join(appRoot, 'ios'));
54
+ const hasAndroidFolder = fs.existsSync(path.join(appRoot, 'android'));
55
+ const hasPodfile = fs.existsSync(path.join(appRoot, 'ios', 'Podfile'));
56
+
57
+ // Check for Expo
58
+ let hasExpo = false;
59
+ try {
60
+ const packageJsonPath = path.join(appRoot, 'package.json');
61
+ if (fs.existsSync(packageJsonPath)) {
62
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
63
+ hasExpo = !!(
64
+ pkg.dependencies?.expo ||
65
+ pkg.devDependencies?.expo ||
66
+ pkg.dependencies?.['expo-modules-core']
67
+ );
68
+ }
69
+ } catch (e) {
70
+ // Ignore errors
71
+ }
72
+
73
+ if (hasExpo && !hasIosFolder && !hasAndroidFolder) {
74
+ return 'expo-managed';
75
+ }
76
+ if (hasExpo && (hasIosFolder || hasAndroidFolder)) {
77
+ return 'expo-bare';
78
+ }
79
+ if (!hasExpo && (hasIosFolder || hasAndroidFolder)) {
80
+ return 'bare-rn';
81
+ }
82
+ return 'unknown';
83
+ }
84
+
85
+ function printBareRNMessage() {
86
+ const c = colors;
87
+ // Use stderr for better visibility (npm sometimes hides stdout from postinstall)
88
+ const log = (msg) => process.stderr.write(msg + '\n');
89
+
90
+ log('');
91
+ log(`${c.bgMagenta}${c.white}${c.bright} ${c.reset}`);
92
+ log(`${c.bgMagenta}${c.white}${c.bright} ╔═══════════════════════════════════════════════════════════════╗ ${c.reset}`);
93
+ log(`${c.bgMagenta}${c.white}${c.bright} ║ ║ ${c.reset}`);
94
+ log(`${c.bgMagenta}${c.white}${c.bright} ║ 🔮 MAGICPIXEL SDK - BARE REACT NATIVE SETUP REQUIRED 🔮 ║ ${c.reset}`);
95
+ log(`${c.bgMagenta}${c.white}${c.bright} ║ ║ ${c.reset}`);
96
+ log(`${c.bgMagenta}${c.white}${c.bright} ╚═══════════════════════════════════════════════════════════════╝ ${c.reset}`);
97
+ log(`${c.bgMagenta}${c.white}${c.bright} ${c.reset}`);
98
+ log('');
99
+ log(`${c.cyan}${c.bright} Complete these steps to finish SDK installation:${c.reset}`);
100
+ log('');
101
+ log(`${c.yellow}${c.bright} STEP 1:${c.reset} Link native modules (iOS)`);
102
+ log(`${c.dim} ─────────────────────────────────────${c.reset}`);
103
+ log(` ${c.white}cd ios && pod install && cd ..${c.reset}`);
104
+ log('');
105
+ log(`${c.yellow}${c.bright} STEP 2:${c.reset} Add polyfill to index.js ${c.dim}(MUST be first import!)${c.reset}`);
106
+ log(`${c.dim} ─────────────────────────────────────${c.reset}`);
107
+ log(` ${c.white}import 'react-native-get-random-values';${c.reset}`);
108
+ log('');
109
+ log(`${c.yellow}${c.bright} STEP 3:${c.reset} Rebuild your app ${c.dim}(required after pod install)${c.reset}`);
110
+ log(`${c.dim} ─────────────────────────────────────${c.reset}`);
111
+ log(` ${c.white}• Kill the app in simulator/device${c.reset}`);
112
+ log(` ${c.white}• Stop Metro (Ctrl+C)${c.reset}`);
113
+ log(` ${c.white}• Run: npx react-native run-ios${c.reset}`);
114
+ log('');
115
+ log(`${c.dim} ⚠️ Without these steps, you'll see:${c.reset}`);
116
+ log(`${c.dim} TurboModuleRegistry.getEnforcing(...): 'RNGetRandomValues' not found${c.reset}`);
117
+ log('');
118
+ log(`${c.dim} 📖 Full docs: https://github.com/digital-madtech/mp-rn-client-sdk#readme${c.reset}`);
119
+ log('');
120
+ }
121
+
122
+ function main() {
123
+ try {
124
+ const appRoot = getAppRoot();
125
+ const projectType = detectProjectType(appRoot);
126
+
127
+ if (projectType === 'bare-rn' || projectType === 'expo-bare') {
128
+ printBareRNMessage();
129
+ }
130
+ // For expo-managed, no message needed - it handles native modules automatically
131
+ } catch (error) {
132
+ // Silently fail - don't break npm install
133
+ }
134
+ }
135
+
136
+ main();