-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This PR adds support for running Expo Go apps in React Native IDE. Most of its logic related with ensuring presence and versioning of Expo Go relies on the code from @expo library. Key features: 1. Recognition of Expo Go usage is accomplished by executing a JavaScript script that utilizes`resolveOptionsAsync` function from @expo. 2. Downloading Expo Go .apk and .app file is also handled by function from @expo. We execute JS script that uses `downloadExpoGoAsync`. 3. Launching the app is performed with the deep link with expo scheme. This functionality was implemented before, but with this PR, we also add the choice of using `expo-go` as the deep link parameter --------- Co-authored-by: Krzysztof Magiera <[email protected]>
- Loading branch information
1 parent
7147f2f
commit 961ae52
Showing
103 changed files
with
30,243 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
const { requireFromAppDir, appRoot } = require("./metro_helpers"); | ||
const { getConfig } = requireFromAppDir("@expo/config/build/Config.js"); | ||
const { downloadExpoGoAsync } = requireFromAppDir("@expo/cli/build/src/utils/downloadExpoGoAsync"); | ||
|
||
async function main() { | ||
let platform = process.argv[2]; // 'Android' or 'iOS' | ||
|
||
if (platform !== "Android" && platform !== "iOS") { | ||
throw new Error("Platform not selected."); | ||
} | ||
const { exp } = getConfig(appRoot); | ||
const sdkVersion = exp.sdkVersion; | ||
|
||
// expo accepts either 'ios' or 'android' | ||
// in RN IDE we use 'Android' or 'iOS', so we need apply toLowerCase | ||
platform = platform.toLowerCase(); | ||
const filepath = await downloadExpoGoAsync(platform, { sdkVersion }); | ||
console.log(filepath); | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const { requireFromAppDir, appRoot } = require("./metro_helpers"); | ||
const { resolveOptionsAsync } = requireFromAppDir("@expo/cli/build/src/start/resolveOptions"); | ||
|
||
// This is a test script to ensure that the `expo-go-project` package can be imported and used in a project. | ||
// It is expected to fail either due to missing imports or because of devClient flag is set which indicates that the project | ||
// is not a Expo Go project. | ||
async function main() { | ||
const { devClient } = await resolveOptionsAsync(appRoot, {}); | ||
if (devClient) { | ||
throw new Error("Dev client is enabled"); | ||
} | ||
} | ||
|
||
main(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import path from "path"; | ||
import { extensionContext, getAppRootFolder } from "../utilities/extensionContext"; | ||
import http from "http"; | ||
import fs from "fs"; | ||
import { exec } from "../utilities/subprocess"; | ||
import { Platform } from "../common/DeviceManager"; | ||
import { CancelToken } from "./BuildManager"; | ||
|
||
type ExpoDeeplinkChoice = "expo-go" | "expo-dev-client"; | ||
|
||
function fileExists(filePath: string, ...additionalPaths: string[]) { | ||
return fs.existsSync(path.join(filePath, ...additionalPaths)); | ||
} | ||
|
||
export async function isExpoGoProject(): Promise<boolean> { | ||
// There is no straightforward way to tell apart different react native project | ||
// setups. i.e. expo-go, expo-dev-client, bare react native, etc. | ||
// Here, we are using a heuristic to determine if the project is expo-go based | ||
// on the following factors: | ||
// 1) The project has app.json or app.config.js | ||
// 2) The project doesn't have an android or ios folder | ||
// 3) The expo_go_project_tester.js script runs successfully – the script uses expo-cli | ||
// internals to resolve project config and tells expo-go and dev-client apart. | ||
const appRoot = getAppRootFolder(); | ||
|
||
if (!fileExists(appRoot, "app.json") && !fileExists(appRoot, "app.config.js")) { | ||
// app.json or app.config.js is required for expo-go projects | ||
return false; | ||
} | ||
|
||
if (fileExists(appRoot, "android") || fileExists(appRoot, "ios")) { | ||
// expo-go projects don't have android or ios folders | ||
return false; | ||
} | ||
|
||
const expoGoProjectTesterScript = path.join( | ||
extensionContext.extensionPath, | ||
"lib", | ||
"expo_go_project_tester.js" | ||
); | ||
try { | ||
const result = await exec(`node`, [expoGoProjectTesterScript], { | ||
cwd: getAppRootFolder(), | ||
allowNonZeroExit: true, | ||
}); | ||
return result.exitCode === 0; | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
|
||
export function fetchExpoLaunchDeeplink( | ||
metroPort: number, | ||
platformString: string, | ||
choice: ExpoDeeplinkChoice | ||
) { | ||
return new Promise<string | void>((resolve, reject) => { | ||
const req = http.request( | ||
new URL( | ||
`http://localhost:${metroPort}/_expo/link?platform=${platformString}&choice=${choice}` | ||
), | ||
(res) => { | ||
if (res.statusCode === 307) { | ||
// we want to retrieve redirect location | ||
resolve(res.headers.location); | ||
} else { | ||
resolve(); | ||
} | ||
res.resume(); | ||
} | ||
); | ||
req.on("error", (e) => { | ||
// we still want to resolve on error, because the URL may not exists, in which | ||
// case it serves as a mechanism for detecting non expo-dev-client setups | ||
resolve(); | ||
}); | ||
req.end(); | ||
}); | ||
} | ||
|
||
export async function downloadExpoGo(platform: Platform, cancelToken: CancelToken) { | ||
const downloadScript = path.join(extensionContext.extensionPath, "lib", "expo_go_download.js"); | ||
const { stdout } = await cancelToken.adapt( | ||
exec(`node`, [downloadScript, platform], { | ||
cwd: getAppRootFolder(), | ||
}) | ||
); | ||
|
||
// While expo downloads the file, it prints '- Fetching Expo Go' and at the last line it prints the path to the downloaded file | ||
// we want to wait until the file is downloaded before we return the path | ||
const lines = stdout.split("\n"); | ||
const filepath = lines[lines.length - 1]; | ||
return filepath; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.