react-native-config 1.6.1 → 1.6.2
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
|
@@ -26,6 +26,9 @@ Keep in mind this module doesn't obfuscate or encrypt secrets for packaging, so
|
|
|
26
26
|
|
|
27
27
|
## Setup
|
|
28
28
|
|
|
29
|
+
> ⚠️ Note (Android): react-native-config v1.6.0+ requires React Native 0.74 or higher.
|
|
30
|
+
> If you use an older RN version, see Troubleshooting below.
|
|
31
|
+
|
|
29
32
|
Install the package:
|
|
30
33
|
|
|
31
34
|
```
|
|
@@ -34,20 +37,34 @@ $ yarn add react-native-config
|
|
|
34
37
|
|
|
35
38
|
Link the library:
|
|
36
39
|
|
|
37
|
-
|
|
40
|
+
On React Native 0.60 and above there is no link step — the library is
|
|
41
|
+
[autolinked](https://reactnative.dev/blog/2019/07/03/version-60#native-modules-are-now-autolinked).
|
|
42
|
+
Rebuild the app so the native side is picked up. On iOS / macOS, install the pod first:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
(cd ios; pod install)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> [!WARNING]
|
|
49
|
+
> Do not link this library manually on React Native 0.60 or above, and do not disable its
|
|
50
|
+
> autolinking in `react-native.config.js`. Autolinking is what registers the native module and,
|
|
51
|
+
> on the New Architecture, generates its TurboModule bindings — adding
|
|
52
|
+
> `include ':react-native-config'` to `android/settings.gradle` instead does neither, and the
|
|
53
|
+
> module then resolves to `null` at runtime. See
|
|
54
|
+
> [TypeError: Cannot read property 'getConfig' of null](#typeerror-cannot-read-property-getconfig-of-null).
|
|
38
55
|
|
|
39
56
|
(Note: For Windows, this module supports autolinking when used with `react-native-windows@0.63`
|
|
40
57
|
or later. For earlier versions you need to manually link the module.)
|
|
41
58
|
|
|
59
|
+
<details>
|
|
60
|
+
<summary><b>Manual linking</b> — only for React Native below 0.60, or react-native-windows below 0.63</summary>
|
|
61
|
+
|
|
42
62
|
```
|
|
43
63
|
$ react-native link react-native-config
|
|
44
64
|
```
|
|
45
65
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
(cd ios; pod install)
|
|
50
|
-
```
|
|
66
|
+
(`react-native link` was removed from the React Native CLI; it is only available on the older
|
|
67
|
+
versions these instructions apply to.)
|
|
51
68
|
|
|
52
69
|
- Manual Link (iOS / macOS)
|
|
53
70
|
|
|
@@ -115,6 +132,8 @@ if cocoapods are used in the project then pod has to be installed as well:
|
|
|
115
132
|
|
|
116
133
|
Add `PackageProviders().Append(winrt::RNCConfig::ReactPackageProvider());` before `InitializeComponent();`.
|
|
117
134
|
|
|
135
|
+
</details>
|
|
136
|
+
|
|
118
137
|
### Extra step for Android
|
|
119
138
|
#### Using RN-Integrate
|
|
120
139
|
Apply extra steps automatically:
|
|
@@ -132,16 +151,29 @@ apply from: project(':react-native-config').projectDir.getPath() + "/dotenv.grad
|
|
|
132
151
|
|
|
133
152
|
#### Advanced Android Setup
|
|
134
153
|
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
`BuildConfig` is generated in your module's `namespace`, which is not always the same as its
|
|
155
|
+
`applicationId` — `applicationIdSuffix` and per-flavor `applicationId` change the latter and
|
|
156
|
+
leave the former alone. The library resolves this for you: it looks for `BuildConfig` in the
|
|
157
|
+
package declaring your `Application` class (that is, the `namespace`) before falling back to the
|
|
158
|
+
`applicationId`, so the common variant setups need no extra configuration.
|
|
159
|
+
|
|
160
|
+
If your `BuildConfig` lives somewhere neither of those points at, name the package explicitly in
|
|
161
|
+
`android/app/build.gradle`:
|
|
137
162
|
|
|
138
163
|
```
|
|
139
164
|
defaultConfig {
|
|
140
165
|
...
|
|
141
|
-
resValue "string", "build_config_package", "
|
|
166
|
+
resValue "string", "build_config_package", "YOUR_NAMESPACE"
|
|
142
167
|
}
|
|
143
168
|
```
|
|
144
169
|
|
|
170
|
+
where `YOUR_NAMESPACE` matches the `namespace` in `android/app/build.gradle` (on React Native
|
|
171
|
+
0.72 and older, the `package` attribute of `<manifest>` in `AndroidManifest.xml`). This value
|
|
172
|
+
takes priority over the automatic resolution above.
|
|
173
|
+
|
|
174
|
+
If the config arrives in JS as `{}`, check logcat for `ReactConfig: Could not find BuildConfig
|
|
175
|
+
class` — the message lists every package that was tried.
|
|
176
|
+
|
|
145
177
|
## TypeScript declaration for your .env file
|
|
146
178
|
|
|
147
179
|
If you want to get autocompletion and typesafety for your .env files. Create a file named `react-native-config.d.ts` in the same directory where you put your type declarations, and add the following contents:
|
|
@@ -395,12 +427,56 @@ If using Dexguard, the shrinking phase will remove resources it thinks are unuse
|
|
|
395
427
|
|
|
396
428
|
-keepresources string/build_config_package
|
|
397
429
|
|
|
430
|
+
### TypeError: Cannot read property 'getConfig' of null
|
|
431
|
+
|
|
432
|
+
The JavaScript side loaded but the native module is not registered in the build, so
|
|
433
|
+
`TurboModuleRegistry` returned `null`. In rough order of likelihood:
|
|
434
|
+
|
|
435
|
+
1. **The app was not rebuilt** after the library was installed. Restarting Metro does not rebuild
|
|
436
|
+
native code — rebuild the app itself.
|
|
437
|
+
2. **Autolinking is disabled for this library.** Look for an entry like this in
|
|
438
|
+
`react-native.config.js` and remove it:
|
|
439
|
+
|
|
440
|
+
```js
|
|
441
|
+
dependencies: {
|
|
442
|
+
'react-native-config': {
|
|
443
|
+
platforms: { android: null }, // <- remove
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
3. **The library is linked manually.** On React Native 0.60+ autolinking replaces manual linking,
|
|
449
|
+
and on the New Architecture a manually linked module is never registered as a TurboModule.
|
|
450
|
+
Remove `include ':react-native-config'` (and the accompanying `project(...)` line) from
|
|
451
|
+
`android/settings.gradle`, and `implementation project(':react-native-config')` from
|
|
452
|
+
`android/app/build.gradle`.
|
|
453
|
+
4. **iOS only:** `pod install` has not been run since the library was installed.
|
|
454
|
+
|
|
455
|
+
After changing any of the above, rebuild from clean — on Android, delete `android/build` and
|
|
456
|
+
`android/app/build` first, since a stale build can keep the old registration.
|
|
457
|
+
|
|
398
458
|
### TypeError: _reactNativeConfig.default.getConstants is not a function
|
|
399
459
|
|
|
400
460
|
This error stems from `.env` file being malformed. Accepted formats are listed here https://regex101.com/r/cbm5Tp/1. Common causes are:
|
|
401
461
|
- Missing the .env file entirely
|
|
402
462
|
- Rogue space anywhere, example: in front of env variable: ` MY_ENV='foo'`
|
|
403
463
|
|
|
464
|
+
### Android build error: cannot find symbol BaseReactPackage
|
|
465
|
+
|
|
466
|
+
Starting from **react-native-config v1.6.0**, the Android implementation uses
|
|
467
|
+
`BaseReactPackage` instead of `ReactPackage`.
|
|
468
|
+
|
|
469
|
+
`BaseReactPackage` was introduced in **React Native 0.74**, so projects on React
|
|
470
|
+
Native 0.73 or older will see build errors like:
|
|
471
|
+
|
|
472
|
+
> cannot find symbol
|
|
473
|
+
> class BaseReactPackage
|
|
474
|
+
|
|
475
|
+
To fix this:
|
|
476
|
+
|
|
477
|
+
- Use `react-native-config` **below 1.6.0** (e.g. `1.5.10`), or
|
|
478
|
+
- Upgrade React Native to **0.74 or higher**
|
|
479
|
+
|
|
404
480
|
## Testing
|
|
405
481
|
|
|
406
482
|
Since `react-native-config` contains native code, it cannot be run in a node.js environment (Jest, Mocha). [react-native-config-node](https://github.com/CureApp/react-native-config-node) provides a way to mock `react-native-config` for use in test runners - exactly as it is used in the actual app.
|
|
@@ -7,12 +7,18 @@ import com.facebook.react.bridge.WritableMap;
|
|
|
7
7
|
import java.lang.ClassNotFoundException;
|
|
8
8
|
import java.lang.IllegalAccessException;
|
|
9
9
|
import java.lang.reflect.Field;
|
|
10
|
+
import java.util.ArrayList;
|
|
11
|
+
import java.util.LinkedHashSet;
|
|
12
|
+
import java.util.List;
|
|
10
13
|
import java.util.Map;
|
|
11
14
|
import java.util.HashMap;
|
|
15
|
+
import java.util.Set;
|
|
12
16
|
|
|
13
17
|
public class RNCConfigModuleImpl {
|
|
14
18
|
public static final String NAME = "RNCConfigModule";
|
|
15
19
|
|
|
20
|
+
private static final String TAG = "ReactNative";
|
|
21
|
+
|
|
16
22
|
private ReactApplicationContext context;
|
|
17
23
|
|
|
18
24
|
public RNCConfigModuleImpl(ReactApplicationContext context) {
|
|
@@ -32,31 +38,78 @@ public class RNCConfigModuleImpl {
|
|
|
32
38
|
// because of type safety on the new arch
|
|
33
39
|
final Map<String, Object> realConstants = new HashMap<>();
|
|
34
40
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
final List<String> candidates = buildConfigPackageCandidates();
|
|
42
|
+
Class<?> clazz = null;
|
|
43
|
+
|
|
44
|
+
for (String candidate : candidates) {
|
|
38
45
|
try {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
clazz = Class.forName(candidate + ".BuildConfig");
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
catch (ClassNotFoundException e) {
|
|
50
|
+
// Not here - try the next candidate.
|
|
42
51
|
}
|
|
43
|
-
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (clazz == null) {
|
|
55
|
+
Log.w(TAG, "ReactConfig: Could not find BuildConfig class. Tried: " + candidates + ". "
|
|
56
|
+
+ "If BuildConfig is generated somewhere else, point the library at it with "
|
|
57
|
+
+ "`resValue \"string\", \"build_config_package\", \"<your namespace>\"` in android/app/build.gradle.");
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
44
60
|
Field[] fields = clazz.getDeclaredFields();
|
|
45
61
|
for(Field f: fields) {
|
|
46
62
|
try {
|
|
47
63
|
realConstants.put(f.getName(), f.get(null));
|
|
48
64
|
}
|
|
49
65
|
catch (IllegalAccessException e) {
|
|
50
|
-
Log.d(
|
|
66
|
+
Log.d(TAG, "ReactConfig: Could not access BuildConfig field " + f.getName());
|
|
51
67
|
}
|
|
52
68
|
}
|
|
53
69
|
}
|
|
54
|
-
catch (ClassNotFoundException e) {
|
|
55
|
-
Log.d("ReactNative", "ReactConfig: Could not find BuildConfig class");
|
|
56
|
-
}
|
|
57
70
|
|
|
58
71
|
ret.put("config", realConstants);
|
|
59
72
|
|
|
60
73
|
return MapConverter.convertMapToWritableMap(ret);
|
|
61
74
|
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Packages that may hold the app's generated BuildConfig, most-specific first.
|
|
78
|
+
*
|
|
79
|
+
* BuildConfig is generated in the module's `namespace`, which is not necessarily the
|
|
80
|
+
* applicationId: `applicationIdSuffix` and per-flavor `applicationId` change the latter and
|
|
81
|
+
* leave the former alone. Resolving only via getPackageName() therefore misses BuildConfig on
|
|
82
|
+
* any such variant, and the config silently arrives in JS as {}.
|
|
83
|
+
*/
|
|
84
|
+
private List<String> buildConfigPackageCandidates() {
|
|
85
|
+
// LinkedHashSet keeps the priority order below while dropping duplicates, which is the
|
|
86
|
+
// common case: for most apps all three candidates are the same string.
|
|
87
|
+
final Set<String> candidates = new LinkedHashSet<>();
|
|
88
|
+
|
|
89
|
+
// 1. An explicit `resValue "string", "build_config_package", "..."`. Honoured first so that
|
|
90
|
+
// existing setups relying on it keep working, and so it stays an escape hatch when the
|
|
91
|
+
// derived candidates below are wrong.
|
|
92
|
+
int resId = this.context.getResources().getIdentifier(
|
|
93
|
+
"build_config_package", "string", this.context.getPackageName());
|
|
94
|
+
if (resId != 0) {
|
|
95
|
+
try {
|
|
96
|
+
candidates.add(this.context.getString(resId));
|
|
97
|
+
}
|
|
98
|
+
catch (Resources.NotFoundException e) {
|
|
99
|
+
// Declared but unreadable - fall through to the derived candidates.
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 2. The package declaring the Application class. That class is part of the app module, so
|
|
104
|
+
// its package is the `namespace` - unaffected by applicationId/applicationIdSuffix.
|
|
105
|
+
Package applicationPackage = this.context.getApplicationContext().getClass().getPackage();
|
|
106
|
+
if (applicationPackage != null) {
|
|
107
|
+
candidates.add(applicationPackage.getName());
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 3. The applicationId. Correct whenever it matches the namespace, which is the default.
|
|
111
|
+
candidates.add(this.context.getApplicationContext().getPackageName());
|
|
112
|
+
|
|
113
|
+
return new ArrayList<>(candidates);
|
|
114
|
+
}
|
|
62
115
|
}
|
package/index.js
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const NativeConfigModule = require("./codegen/NativeConfigModule").default;
|
|
4
|
+
|
|
5
|
+
if (NativeConfigModule == null) {
|
|
6
|
+
// TurboModuleRegistry.get returns null when the native module is not registered in the app.
|
|
7
|
+
// Left alone, the next line fails with "Cannot read property 'getConfig' of null", which says
|
|
8
|
+
// nothing about the cause - so spell out the ones that actually produce this.
|
|
9
|
+
throw new Error(
|
|
10
|
+
"react-native-config: the native module RNCConfigModule was not found.\n\n" +
|
|
11
|
+
"JavaScript loaded, but the native side is not registered in this build. Common causes:\n\n" +
|
|
12
|
+
" 1. The app was not rebuilt after installing the library. Restarting Metro is not enough -\n" +
|
|
13
|
+
" rebuild the native app.\n" +
|
|
14
|
+
" 2. Autolinking is disabled for this library. Check react-native.config.js for a\n" +
|
|
15
|
+
" `dependencies` entry setting `platforms.android` or `platforms.ios` to null, and\n" +
|
|
16
|
+
" remove it.\n" +
|
|
17
|
+
" 3. The library is linked manually. React Native 0.60+ autolinks it, and on the New\n" +
|
|
18
|
+
" Architecture a manually linked module is not registered as a TurboModule. Remove\n" +
|
|
19
|
+
" `include ':react-native-config'` from android/settings.gradle and the matching\n" +
|
|
20
|
+
" `implementation project(':react-native-config')` from android/app/build.gradle.\n" +
|
|
21
|
+
" 4. iOS only: `pod install` has not run since the library was installed.\n\n" +
|
|
22
|
+
"See https://github.com/react-native-config/react-native-config#troubleshooting"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const Config = NativeConfigModule.getConfig().config;
|
|
5
27
|
export default Config;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-config",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"description": "Expose config variables to React Native apps",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"env",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"windows",
|
|
13
13
|
"12factor"
|
|
14
14
|
],
|
|
15
|
-
"homepage": "https://github.com/
|
|
15
|
+
"homepage": "https://github.com/react-native-config/react-native-config",
|
|
16
16
|
"contributors": [
|
|
17
17
|
"Luan Curti <luancurti@gmail.com> (https://github.com/luancurti)",
|
|
18
18
|
"Amer Lotfi Orimi <amerllica@gmail.com> (https://github.com/amerllica)"
|
|
19
19
|
],
|
|
20
20
|
"repository": {
|
|
21
21
|
"type": "git",
|
|
22
|
-
"url": "https://github.com/
|
|
22
|
+
"url": "git+https://github.com/react-native-config/react-native-config.git"
|
|
23
23
|
},
|
|
24
24
|
"private": false,
|
|
25
25
|
"author": "Pedro Belo",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"ios": {
|
|
64
64
|
"modules": {
|
|
65
|
-
"
|
|
65
|
+
"RNCConfigModule": {
|
|
66
66
|
"className": "RNCConfigModule",
|
|
67
67
|
"unstableRequiresMainQueueSetup": true
|
|
68
68
|
}
|