Repository: microsoft/react-native-test-app
Pull request #739 (2022-02-02 15:08:15)

fix: add support for react-native 0.68
### Description

- ~~react-native 0.68 discussion: https://github.com/reactwg/react-native-releases/discussions/13~~
- react-native 0.68 (part 2) discussion: https://github.com/reactwg/react-native-releases/discussions/17
- react-native-windows 0.68: https://github.com/microsoft/react-native-windows/issues/9486

### Blocked by

- [x] #759
- [x] #762
- [x] #838
- [x] #837

### Platforms affected

- [x] Android
- [x] iOS
- [ ] macOS
- [x] Windows

### Test plan

1. Set version 0.68:
   ```
   npm run set-react-version 0.68
   yarn
   cd example
   ```
2. Build and run Android app:
   ```
   yarn android
   ```
3. Build and run iOS app:
   ```
   rm -rf ios/Podfile.lock ios/Pods
   pod install --project-directory=ios
   yarn ios
   ```
4. Enable Hermes by applying the patch below, and repeat step 3:
   ```diff
   diff --git a/example/ios/Podfile b/example/ios/Podfile
   index b6eae97..3d4a840 100644
   --- a/example/ios/Podfile
   +++ b/example/ios/Podfile
   @@ -4,7 +4,7 @@ workspace 'Example.xcworkspace'
   
    use_flipper! false if ENV['DISABLE_FLIPPER']
   
   -use_test_app! :hermes_enabled => false do |target|
   +use_test_app! :hermes_enabled => true do |target|
      target.tests do
        pod 'Example-Tests', :path => '..'
      end
   ```
5. Build and run Windows app:
   ```
   yarn install-windows-test-app
   yarn windows
   ```


| Screen | Android (Hermes) | iOS (JSC) | iOS (Hermes) | Windows |
| :- | :-: | :-: | :-: | :-: |
| Home | ![Screenshot_1643917255](https://user-images.githubusercontent.com/4123478/152417249-19166491-979e-4ea1-874b-7bfa93d6aa63.png) | ![image](https://user-images.githubusercontent.com/4123478/152175832-7d7cb625-4188-485e-b155-cf2260ef0d56.png) | ![image](https://user-images.githubusercontent.com/4123478/152177606-b000e977-bd94-4421-9ac2-43d1fa73beb3.png) | n/a |
| App | ![Screenshot_1643917264](https://user-images.githubusercontent.com/4123478/152417266-a5552651-084c-4372-b2d9-7767ffec3d46.png) | ![image](https://user-images.githubusercontent.com/4123478/152175881-d2d2aeea-708e-4044-b075-119bd47c4b65.png) | ![image](https://user-images.githubusercontent.com/4123478/152177644-98eb2320-1e5b-460e-bce8-fea7961e84e4.png) | ![image](https://user-images.githubusercontent.com/4123478/160417309-4f5890f5-4ca6-4896-9c5e-ed463189517e.png) |

tido64: Last tested against:

```js
{
  '@react-native-community/cli': '^7.0.3',
  '@react-native-community/cli-platform-android': '^7.0.1',
  '@react-native-community/cli-platform-ios': '^7.0.1',
  'hermes-engine': '~0.11.0',
  'metro-react-native-babel-preset': '0.67.0',
  react: '17.0.2',
  'react-native': '0.68.0-rc.4',
  'react-native-macos': undefined,
  'react-native-windows': '0.68.0-preview.7'
}
```

Patch:
diff --git a/android/gradle.properties b/android/gradle.properties
index 3785375..c409761 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,25 +1,35 @@
 # Project-wide Gradle settings.
+
 # IDE (e.g. Android Studio) users:
 # Gradle settings configured through the IDE *will override*
 # any settings specified in this file.
+
 # For more details on how to configure your build environment visit
 # http://www.gradle.org/docs/current/userguide/build_environment.html
-# Specifies the JVM arguments used for the daemon process.
-# The setting is particularly useful for tweaking memory settings.
-org.gradle.jvmargs=-Xmx1536m
-# When configured, Gradle will run in incubating parallel mode.
-# This option should only be used with decoupled projects. More details, visit
-# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
-# org.gradle.parallel=true
+
+# Specifies the JVM arguments used for the Gradle Daemon. The setting is
+# particularly useful for configuring JVM memory settings for build performance.
+# This does not affect the JVM settings for the Gradle client VM.
+# The default is `-Xmx512m -XX:MaxMetaspaceSize=256m`.
+org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will fork up to org.gradle.workers.max JVMs to execute
+# projects in parallel. To learn more about parallel task execution, see the
+# section on Gradle build performance:
+# https://docs.gradle.org/current/userguide/performance.html#parallel_execution.
+# Default is `false`.
+#org.gradle.parallel=true
+
 # AndroidX package structure to make it clearer which packages are bundled with the
 # Android operating system, and which are packaged with your app's APK
 # https://developer.android.com/topic/libraries/support-library/androidx-rn
 android.useAndroidX=true
 # Automatically convert third-party libraries to use AndroidX
 android.enableJetifier=true
-# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
 
 # Failed to transform '/~/bcprov-jdk15on-1.68.jar' using Jetifier.
 # Reason: IllegalArgumentException, message: Unsupported class file major version 59.
 android.jetifier.ignorelist=bcprov-jdk15on
+
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
diff --git a/example/package.json b/example/package.json
index d3b2e3b..87bdf19 100644
--- a/example/package.json
+++ b/example/package.json
@@ -17,10 +17,10 @@
     "windows": "react-native run-windows --no-packager"
   },
   "peerDependencies": {
-    "react": "~16.8.6 || ~16.9.0 || ~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2",
-    "react-native": "^0.0.0-0 || 0.60 - 0.67 || 1000.0.0",
-    "react-native-macos": "^0.0.0-0 || 0.60 - 0.66",
-    "react-native-windows": "^0.0.0-0 || 0.62 - 0.67"
+    "react": "~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2",
+    "react-native": "^0.0.0-0 || 0.62 - 0.68 || 1000.0.0",
+    "react-native-macos": "^0.0.0-0 || 0.62 - 0.66",
+    "react-native-windows": "^0.0.0-0 || 0.62 - 0.68"
   },
   "devDependencies": {
     "@babel/core": "^7.0.0",
diff --git a/example/react-native.config.js b/example/react-native.config.js
index 262d4b8..9b40783 100644
--- a/example/react-native.config.js
+++ b/example/react-native.config.js
@@ -1,24 +1,31 @@
-const fs = require("fs");
-const path = require("path");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require("react-native-test-app");
+const project = (() => {
+  const fs = require("fs");
+  const path = require("path");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require("react-native-test-app");
+    return {
+      android: {
+        sourceDir: "android",
+        manifestPath: androidManifestPath(path.join(__dirname, "android")),
+      },
+      ios: {
+        project: iosProjectPath("ios"),
+      },
+      windows: fs.existsSync("windows/Example.sln") && {
+        sourceDir: "windows",
+        solutionFile: "Example.sln",
+        project: windowsProjectPath(path.join(__dirname, "windows")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: "android",
-      manifestPath: androidManifestPath(path.join(__dirname, "android")),
-    },
-    ios: {
-      project: iosProjectPath("ios"),
-    },
-    windows: fs.existsSync("windows/Example.sln") && {
-      sourceDir: "windows",
-      solutionFile: "Example.sln",
-      project: windowsProjectPath(path.join(__dirname, "windows")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
diff --git a/package.json b/package.json
index 4ff45b4..9c886ca 100644
--- a/package.json
+++ b/package.json
@@ -80,9 +80,9 @@
     "@react-native-community/cli-platform-ios": ">=4.10.0",
     "mustache": "^4.0.0",
     "react": "~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2",
-    "react-native": "^0.0.0-0 || 0.62 - 0.67 || 1000.0.0",
+    "react-native": "^0.0.0-0 || 0.62 - 0.68 || 1000.0.0",
     "react-native-macos": "^0.0.0-0 || 0.62 - 0.66",
-    "react-native-windows": "^0.0.0-0 || 0.62 - 0.67"
+    "react-native-windows": "^0.0.0-0 || 0.62 - 0.68"
   },
   "peerDependenciesMeta": {
     "@react-native-community/cli": {
diff --git a/scripts/configure.js b/scripts/configure.js
index bc55c16..ce73ea6 100755
--- a/scripts/configure.js
+++ b/scripts/configure.js
@@ -282,14 +282,22 @@ function reactNativeConfig({ name, testAppPath, platforms, flatten }) {
     switch (platforms[0]) {
       case "android":
         return join(
-          'const { androidManifestPath } = require("react-native-test-app");',
+          "const project = (() => {",
+          "  try {",
+          '    const { androidManifestPath } = require("react-native-test-app");',
+          "    return {",
+          "      android: {",
+          '        sourceDir: ".",',
+          "        manifestPath: androidManifestPath(__dirname),",
+          "      },",
+          "    };",
+          "  } catch (_) {",
+          "    return undefined;",
+          "  }",
+          "})();",
+          "",
           "module.exports = {",
-          "  project: {",
-          "    android: {",
-          '      sourceDir: ".",',
-          "      manifestPath: androidManifestPath(__dirname),",
-          "    },",
-          "  },",
+          "  ...(project ? { project } : undefined),",
           "};",
           ""
         );
@@ -297,31 +305,46 @@ function reactNativeConfig({ name, testAppPath, platforms, flatten }) {
       case "macos":
       case "ios":
         return join(
-          'const { iosProjectPath } = require("react-native-test-app");',
-          "module.exports = {",
-          "  project: {",
-          "    ios: {",
-          '      project: iosProjectPath("."),',
-          "    }",
+          "const project = (() => {",
+          "  try {",
+          '    const { iosProjectPath } = require("react-native-test-app");',
+          "    return {",
+          "      ios: {",
+          '        project: iosProjectPath("."),',
+          "      },",
+          "    };",
+          "  } catch (_) {",
+          "    return undefined;",
           "  }",
+          "})();",
+          "",
+          "module.exports = {",
+          "  ...(project ? { project } : undefined),",
           "};",
           ""
         );
 
       case "windows":
         return join(
-          'const path = require("path");',
-          'const { windowsProjectPath } = require("react-native-test-app");',
+          "const project = (() => {",
+          '  const path = require("path");',
+          '  const sourceDir = "windows";',
+          "  try {",
+          '    const { windowsProjectPath } = require("react-native-test-app");',
+          "    return {",
+          "      windows: {",
+          "        sourceDir,",
+          `        solutionFile: "${name}.sln",`,
+          "        project: windowsProjectPath(path.join(__dirname, sourceDir)),",
+          "      },",
+          "    };",
+          "  } catch (_) {",
+          "    return undefined;",
+          "  }",
+          "})();",
           "",
-          'const sourceDir = "windows";',
           "module.exports = {",
-          "  project: {",
-          "    windows: {",
-          "      sourceDir,",
-          `      solutionFile: "${name}.sln",`,
-          "      project: windowsProjectPath(path.join(__dirname, sourceDir)),",
-          "    },",
-          "  },",
+          "  ...(project ? { project } : undefined),",
           '  reactNativePath: "node_modules/react-native-windows",',
           "};",
           ""
diff --git a/yarn.lock b/yarn.lock
index 133f41b..d585fb9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5414,10 +5414,10 @@ __metadata:
     react-native-test-app: "workspace:."
     react-native-windows: ^0.66.11
   peerDependencies:
-    react: ~16.8.6 || ~16.9.0 || ~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2
-    react-native: ^0.0.0-0 || 0.60 - 0.67 || 1000.0.0
-    react-native-macos: ^0.0.0-0 || 0.60 - 0.66
-    react-native-windows: ^0.0.0-0 || 0.62 - 0.67
+    react: ~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2
+    react-native: ^0.0.0-0 || 0.62 - 0.68 || 1000.0.0
+    react-native-macos: ^0.0.0-0 || 0.62 - 0.66
+    react-native-windows: ^0.0.0-0 || 0.62 - 0.68
   languageName: unknown
   linkType: soft
 
@@ -10634,9 +10634,9 @@ __metadata:
     "@react-native-community/cli-platform-ios": ">=4.10.0"
     mustache: ^4.0.0
     react: ~16.11.0 || ~16.13.1 || ~17.0.1 || ~17.0.2
-    react-native: ^0.0.0-0 || 0.62 - 0.67 || 1000.0.0
+    react-native: ^0.0.0-0 || 0.62 - 0.68 || 1000.0.0
     react-native-macos: ^0.0.0-0 || 0.62 - 0.66
-    react-native-windows: ^0.0.0-0 || 0.62 - 0.67
+    react-native-windows: ^0.0.0-0 || 0.62 - 0.68
   peerDependenciesMeta:
     "@react-native-community/cli":
       optional: true


Test patch:
diff --git a/test/configure/__snapshots__/gatherConfig.test.js.snap b/test/configure/__snapshots__/gatherConfig.test.js.snap
index 0eeeece..86e7058 100644
--- a/test/configure/__snapshots__/gatherConfig.test.js.snap
+++ b/test/configure/__snapshots__/gatherConfig.test.js.snap
@@ -24,13 +24,21 @@ use_test_app!
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const { iosProjectPath } = require(\\"react-native-test-app\\");
-module.exports = {
-  project: {
-    ios: {
-      project: iosProjectPath(\\".\\"),
-    }
+    "react-native.config.js": "const project = (() => {
+  try {
+    const { iosProjectPath } = require(\\"react-native-test-app\\");
+    return {
+      ios: {
+        project: iosProjectPath(\\".\\"),
+      },
+    };
+  } catch (_) {
+    return undefined;
   }
+})();
+
+module.exports = {
+  ...(project ? { project } : undefined),
 };
 ",
   },
@@ -126,29 +134,36 @@ use_test_app!
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
   },
@@ -193,57 +208,71 @@ Object {
     "common/metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "common/react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "common/react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
   },
@@ -278,29 +307,36 @@ use_test_app!
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
   },
@@ -405,29 +441,36 @@ use_test_app!
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
     "windows/.gitignore": Object {
@@ -539,29 +582,36 @@ use_test_app!
     "metro.config.js": Object {
       "source": "example/metro.config.js",
     },
-    "react-native.config.js": "const fs = require(\\"fs\\");
-const path = require(\\"path\\");
-const {
-  androidManifestPath,
-  iosProjectPath,
-  windowsProjectPath,
-} = require(\\"react-native-test-app\\");
+    "react-native.config.js": "const project = (() => {
+  const fs = require(\\"fs\\");
+  const path = require(\\"path\\");
+  try {
+    const {
+      androidManifestPath,
+      iosProjectPath,
+      windowsProjectPath,
+    } = require(\\"react-native-test-app\\");
+    return {
+      android: {
+        sourceDir: \\"android\\",
+        manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
+      },
+      ios: {
+        project: iosProjectPath(\\"ios\\"),
+      },
+      windows: fs.existsSync(\\"windows/Test.sln\\") && {
+        sourceDir: \\"windows\\",
+        solutionFile: \\"Test.sln\\",
+        project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
+      },
+    };
+  } catch (_) {
+    return undefined;
+  }
+})();
 
 module.exports = {
-  project: {
-    android: {
-      sourceDir: \\"android\\",
-      manifestPath: androidManifestPath(path.join(__dirname, \\"android\\")),
-    },
-    ios: {
-      project: iosProjectPath(\\"ios\\"),
-    },
-    windows: fs.existsSync(\\"windows/Test.sln\\") && {
-      sourceDir: \\"windows\\",
-      solutionFile: \\"Test.sln\\",
-      project: windowsProjectPath(path.join(__dirname, \\"windows\\")),
-    },
-  },
+  ...(project ? { project } : undefined),
 };
 ",
   },