microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
dev/v-peq/remove-unused-xdl-deprecated-fields

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/commands/installExpoGoApplication.ts

174lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import assert = require("assert");
5import * as fs from "fs";
6import * as https from "https";
7import * as os from "os";
8import * as vscode from "vscode";
9import * as nls from "vscode-nls";
10import { OutputChannelLogger } from "../log/OutputChannelLogger";
11import { ErrorHelper } from "../../common/error/errorHelper";
12import { InternalErrorCode } from "../../common/error/internalErrorCode";
13import { downloadExpoGo } from "../../common/downloadHelper";
14import { installAndroidApplication, installiOSApplication } from "../../common/installHelper";
15import { Command } from "./util/command";
16
17nls.config({
18 messageFormat: nls.MessageFormat.bundle,
19 bundleFormat: nls.BundleFormat.standalone,
20})();
21const localize = nls.loadMessageBundle();
22const logger = OutputChannelLogger.getMainChannel();
23
24export class InstallExpoGoApplication extends Command {
25 codeName = "installExpoGoApplication";
26 label = "Download and install Expo Go on simulator or device";
27 error = ErrorHelper.getInternalError(InternalErrorCode.FailedToInstallExpoGo);
28
29 async baseFn(): Promise<void> {
30 assert(this.project);
31 const item = await vscode.window.showQuickPick(["Android", "iOS"], {
32 placeHolder: "Select type for mobile OS",
33 });
34 const installItem = await vscode.window.showQuickPick(["Manual", "Auto"], {
35 placeHolder: "How to install application",
36 });
37 const expoHelper = this.project.getExponentHelper();
38 logger.info(localize("CheckExpoEnvironment", "Checking Expo project environment."));
39 const isExpo = await expoHelper.isExpoManagedApp(true);
40
41 const expoGoListAPI = "https://api.expo.dev/v2/versions";
42 const apiJson = await fetchJson(expoGoListAPI);
43 const jsonContent = JSON.parse(apiJson);
44
45 if (isExpo) {
46 const currentSdkVersion = await expoHelper.exponentSdk(true);
47 const expoUrlInfo = jsonContent.sdkVersions[currentSdkVersion];
48
49 if (item == "Android") {
50 void vscode.window.showInformationMessage("Downloading Expo Go for Android.");
51 logger.logStream(
52 localize("DownloadAndroidExpoGo", "\nDownloading Expo Go for Android. \n"),
53 );
54
55 const targetUrl = expoUrlInfo.androidClientUrl;
56 const androidClientVersion = validateVersion(
57 expoUrlInfo.androidClientVersion as string,
58 );
59 const fileName = `${this.project
60 .getPackager()
61 .getProjectPath()}/expogo_${androidClientVersion}.apk`;
62
63 if (!fs.existsSync(fileName)) {
64 try {
65 await downloadExpoGo(targetUrl, fileName);
66 } catch {
67 throw new Error(
68 localize("FailedToDownloadExpoGo", "Failed to download Expo Go."),
69 );
70 }
71 }
72
73 if (installItem == "Auto") {
74 try {
75 await installAndroidApplication(this.project, fileName);
76 } catch {
77 throw new Error(
78 localize("FailedToInstallExpoGo", "Failed to install Expo Go."),
79 );
80 }
81 } else {
82 logger.logStream(
83 localize(
84 "ManualInstall",
85 "Please manually install Expo Go from project root path. \n",
86 ),
87 );
88 }
89 } else if (item == "iOS") {
90 if (os.platform() != "darwin") {
91 logger.warning(
92 localize(
93 "NotDarwinPlatform",
94 "Current OS may not support iOS installer. The Expo Go may not be installed.\n",
95 ),
96 );
97 }
98 void vscode.window.showInformationMessage("Downloading Expo Go for iOS.");
99 logger.logStream(
100 localize("DownloadiOSExpoGo", "\nDownloading Expo Go for iOS. \n"),
101 );
102
103 const targetUrl = expoUrlInfo.iosClientUrl;
104 const iOSClientVersion = validateVersion(expoUrlInfo.iosClientVersion as string);
105
106 const tarFile = `${this.project
107 .getPackager()
108 .getProjectPath()}/expogo_${iOSClientVersion}.tar.gz`;
109
110 if (!fs.existsSync(tarFile)) {
111 try {
112 await downloadExpoGo(
113 targetUrl,
114 `${this.project
115 .getPackager()
116 .getProjectPath()}/expogo_${iOSClientVersion}.tar.gz`,
117 );
118 } catch {
119 throw new Error(
120 localize("FailedToDownloadExpoGo", "Failed to download Expo Go."),
121 );
122 }
123 }
124
125 if (installItem == "Auto" && os.platform() == "darwin") {
126 try {
127 await installiOSApplication(this.project, tarFile);
128 } catch {
129 throw new Error(
130 localize("FailedToInstallExpoGo", "Failed to install Expo Go."),
131 );
132 }
133 } else {
134 logger.logStream(
135 localize(
136 "CannotAutoInstall",
137 "Cannot auto install Expo Go, selected manual install or target machine is not MacOS. \n",
138 ),
139 );
140 }
141 } else {
142 return;
143 }
144 } else {
145 throw new Error(localize("NotExpoProject", "Current project is not Expo managed."));
146 }
147 }
148}
149
150async function fetchJson(url: string): Promise<string> {
151 return new Promise<string>((fulfill, reject) => {
152 const request = https.get(url, response => {
153 let data = "";
154 response.setEncoding("utf8");
155 response.on("data", (chunk: string) => {
156 data += chunk;
157 });
158 response.on("end", () => fulfill(data));
159 response.on("error", reject);
160 });
161
162 request.on("error", reject);
163 request.end();
164 });
165}
166
167const versionPattern = /^[0-9][0-9.]*$/;
168
169function validateVersion(version: string): string {
170 if (!versionPattern.test(version)) {
171 throw new Error(`Invalid Expo Go version string: ${version}`);
172 }
173 return version;
174}
175