microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix-ts-error1

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/exponent/exponentHelper.ts

542lines · modeblame

1c32fe84Patricio Beltran9 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
09f6024fHeniker4 years ago4// eslint-disable-next-line @typescript-eslint/triple-slash-reference
94cd5149Artem Egorov8 years ago5/// <reference path="exponentHelper.d.ts" />
6
1c32fe84Patricio Beltran9 years ago7import * as path from "path";
57fee98eEzio Li3 years ago8import * as fs from "fs";
8f50947fRedMickey5 years ago9import * as semver from "semver";
efb436fcRedMickey5 years ago10import * as vscode from "vscode";
866e020bRedMickey4 years ago11import { sync as globSync } from "glob";
d7d405aeYuri Skorokhodov7 years ago12import * as nls from "vscode-nls";
623be8a6Ezio Li2 years ago13import { logger } from "@vscode/debugadapter";
dc94981bQuan Jin3 years ago14import { stripJsonTrailingComma, getNodeModulesGlobalPath } from "../../common/utils";
66412fdfRuslan Bikkinin7 years ago15import { Package, IPackageInformation } from "../../common/node/package";
e3706a1cRedMickey6 years ago16import { ProjectVersionHelper } from "../../common/projectVersionHelper";
34472878RedMickey5 years ago17import { OutputChannelLogger } from "../log/OutputChannelLogger";
d7d405aeYuri Skorokhodov7 years ago18import { ErrorHelper } from "../../common/error/errorHelper";
892f0aa6JiglioNero4 years ago19import { PackageLoader, PackageConfig } from "../../common/packageLoader";
d7d405aeYuri Skorokhodov7 years ago20import { InternalErrorCode } from "../../common/error/internalErrorCode";
ce5e88eeYuri Skorokhodov5 years ago21import { FileSystem } from "../../common/node/fileSystem";
892f0aa6JiglioNero4 years ago22import { SettingsHelper } from "../settingsHelper";
09f6024fHeniker4 years ago23import * as XDL from "./xdlInterface";
24
34472878RedMickey5 years ago25nls.config({
26messageFormat: nls.MessageFormat.bundle,
27bundleFormat: nls.BundleFormat.standalone,
28})();
d7d405aeYuri Skorokhodov7 years ago29const localize = nls.loadMessageBundle();
1c32fe84Patricio Beltran9 years ago30
94cd5149Artem Egorov8 years ago31const APP_JSON = "app.json";
32const EXP_JSON = "exp.json";
1c32fe84Patricio Beltran9 years ago33
34const EXPONENT_INDEX = "exponentIndex.js";
94cd5149Artem Egorov8 years ago35const DEFAULT_EXPONENT_INDEX = "index.js";
1c32fe84Patricio Beltran9 years ago36const DEFAULT_IOS_INDEX = "index.ios.js";
37const DEFAULT_ANDROID_INDEX = "index.android.js";
38
94cd5149Artem Egorov8 years ago39const DBL_SLASHES = /\\/g;
1c32fe84Patricio Beltran9 years ago40
efb436fcRedMickey5 years ago41const NGROK_PACKAGE = "@expo/ngrok";
42
1c32fe84Patricio Beltran9 years ago43export class ExponentHelper {
38edb09eAlexander Sorokin9 years ago44private workspaceRootPath: string;
94cd5149Artem Egorov8 years ago45private projectRootPath: string;
2956dba4Yuri Skorokhodov7 years ago46private fs: FileSystem;
a57e740bPatricio Beltran9 years ago47private hasInitialized: boolean;
efb436fcRedMickey5 years ago48private nodeModulesGlobalPathAddedToEnv: boolean;
0a68f8dbArtem Egorov8 years ago49private logger: OutputChannelLogger = OutputChannelLogger.getMainChannel();
1c32fe84Patricio Beltran9 years ago50
34472878RedMickey5 years ago51public constructor(
52workspaceRootPath: string,
53projectRootPath: string,
54fs: FileSystem = new FileSystem(),
55) {
38edb09eAlexander Sorokin9 years ago56this.workspaceRootPath = workspaceRootPath;
57this.projectRootPath = projectRootPath;
2956dba4Yuri Skorokhodov7 years ago58this.fs = fs;
a57e740bPatricio Beltran9 years ago59this.hasInitialized = false;
60// Constructor is slim by design. This is to add as less computation as possible
61// to the initialization of the extension. If a public method is added, make sure
dc94981bQuan Jin3 years ago62// to call this.lazilyInitialize() at the beginning of the code to be sure all variables
a57e740bPatricio Beltran9 years ago63// are correctly initialized.
efb436fcRedMickey5 years ago64this.nodeModulesGlobalPathAddedToEnv = false;
1c32fe84Patricio Beltran9 years ago65}
66
716f31d0JiglioNero5 years ago67public async preloadExponentDependency(): Promise<[typeof xdl, typeof metroConfig]> {
34472878RedMickey5 years ago68this.logger.info(
69localize(
70"MakingSureYourProjectUsesCorrectExponentDependencies",
71"Making sure your project uses the correct dependencies for Expo. This may take a while...",
72),
73);
716f31d0JiglioNero5 years ago74return Promise.all([XDL.getXDLPackage(), XDL.getMetroConfigPackage()]);
75}
76
0d77292aJiglioNero4 years ago77public async configureExponentEnvironment(): Promise<void> {
78await this.lazilyInitialize();
79this.logger.logStream(
80localize("CheckingIfThisIsExpoApp", "Checking if this is an Expo app."),
81);
3cf8f692Ezio Li3 years ago82this.logger.logStream("\n");
83
84const packageJson = await this.getAppPackageInformation();
85if (!packageJson.name || !packageJson.version) {
86this.logger.warning(
87localize(
88"MissingFieldsInExpoApp",
89"Missing 'name' or 'version' field in package.json. These fields might be required for your application.",
90),
91);
92}
93
09f6024fHeniker4 years ago94const isExpo = await this.isExpoManagedApp(true);
0d77292aJiglioNero4 years ago95if (!isExpo) {
96if (!(await this.appHasExpoInstalled())) {
97// Expo requires expo package to be installed inside RN application in order to be able to run it
98// https://github.com/expo/expo-cli/issues/255#issuecomment-453214632
99this.logger.logStream("\n");
716f31d0JiglioNero5 years ago100this.logger.logStream(
0d77292aJiglioNero4 years ago101localize(
102"ExpoPackageIsNotInstalled",
103'[Warning] Please make sure that expo package is installed locally for your project, otherwise further errors may occur. Please, run "npm install expo --save-dev" inside your project to install it.',
104),
716f31d0JiglioNero5 years ago105);
0d77292aJiglioNero4 years ago106this.logger.logStream("\n");
107}
108}
109this.logger.logStream(".\n");
110await this.patchAppJson(isExpo);
d1d77244Jimmy Thomson9 years ago111}
112
113/**
114* Returns the current user. If there is none, asks user for username and password and logins to exponent servers.
115*/
0d77292aJiglioNero4 years ago116public async loginToExponent(
ce5e88eeYuri Skorokhodov5 years ago117promptForInformation: (message: string, password: boolean) => Promise<string>,
34472878RedMickey5 years ago118showMessage: (message: string) => Promise<string>,
ce5e88eeYuri Skorokhodov5 years ago119): Promise<XDL.IUser> {
0d77292aJiglioNero4 years ago120await this.lazilyInitialize();
121let user = await XDL.currentUser();
122if (!user) {
123await showMessage(
124localize(
125"YouNeedToLoginToExpo",
126"You need to login to Expo. Please provide your Expo account username and password in the input boxes after closing this window. If you don't have an account, please go to https://expo.io to create one.",
127),
128);
129const username = await promptForInformation(
130localize("ExpoUsername", "Expo username"),
131false,
132);
133const password = await promptForInformation(
134localize("ExpoPassword", "Expo password"),
135true,
136);
137user = await XDL.login(username, password);
138}
139return user;
6458f408Nikita Matrosov9 years ago140}
141
242759feJiglioNero5 years ago142public async getExpPackagerOptions(projectRoot: string): Promise<ExpMetroConfig> {
716f31d0JiglioNero5 years ago143await this.lazilyInitialize();
242759feJiglioNero5 years ago144const options = await this.getFromExpConfig<any>("packagerOpts").then(opts => opts || {});
145const metroConfig = await this.getArgumentsFromExpoMetroConfig(projectRoot);
146return { ...options, ...metroConfig };
66412fdfRuslan Bikkinin7 years ago147}
148
0d77292aJiglioNero4 years ago149public async appHasExpoInstalled(): Promise<boolean> {
150const packageJson = await this.getAppPackageInformation();
151if (packageJson.dependencies && packageJson.dependencies.expo) {
152this.logger.debug("'expo' package is found in 'dependencies' section of package.json");
153return true;
154} else if (packageJson.devDependencies && packageJson.devDependencies.expo) {
155this.logger.debug(
156"'expo' package is found in 'devDependencies' section of package.json",
157);
158return true;
159}
160return false;
66412fdfRuslan Bikkinin7 years ago161}
162
866e020bRedMickey4 years ago163public async isExpoManagedApp(showProgress: boolean = false): Promise<boolean> {
db6fd42aRuslan Bikkinin7 years ago164if (showProgress) {
165this.logger.logStream("...");
166}
167
0d77292aJiglioNero4 years ago168try {
866e020bRedMickey4 years ago169const expoInstalled = await this.appHasExpoInstalled();
170if (!expoInstalled) return false;
171
172const isBareWorkflowProject = await this.isBareWorkflowProject();
0d77292aJiglioNero4 years ago173if (showProgress) this.logger.logStream(".");
866e020bRedMickey4 years ago174return !isBareWorkflowProject;
0d77292aJiglioNero4 years ago175} catch (e) {
176this.logger.error(e.message, e, e.stack);
177if (showProgress) {
178this.logger.logStream(".");
179}
180// Not in a react-native project
181return false;
182}
db6fd42aRuslan Bikkinin7 years ago183}
184
0d77292aJiglioNero4 years ago185public async findOrInstallNgrokGlobally(): Promise<void> {
186let ngrokInstalled: boolean;
187try {
188await this.addNodeModulesPathToEnvIfNotPresent();
189ngrokInstalled = await XDL.isNgrokInstalled(this.projectRootPath);
190} catch (e) {
191ngrokInstalled = false;
192}
193if (!ngrokInstalled) {
c0dc4020etatanova4 years ago194const ngrokVersion = SettingsHelper.getExpoDependencyVersion("@expo/ngrok");
0d77292aJiglioNero4 years ago195const ngrokPackageConfig = new PackageConfig(NGROK_PACKAGE, ngrokVersion);
196
197const outputMessage = localize(
198"ExpoInstallNgrokGlobally",
199'It seems that "{0}" package isn\'t installed globally. This package is required to use Expo tunnels, would you like to install it globally?',
200ngrokPackageConfig.getStringForInstall(),
201);
202const installButton = localize("InstallNgrokGloballyButtonOK", "Install");
203const cancelButton = localize("InstallNgrokGloballyButtonCancel", "Cancel");
204
205const selectedItem = await vscode.window.showWarningMessage(
206outputMessage,
207installButton,
208cancelButton,
209);
210if (selectedItem === installButton) {
211await PackageLoader.getInstance().installGlobalPackage(
212ngrokPackageConfig,
213this.projectRootPath,
214);
215this.logger.info(
216localize(
217"NgrokInstalledGlobally",
218'"{0}" package has been successfully installed globally.',
0690ab22RedMickey4 years ago219ngrokPackageConfig.getStringForInstall(),
0d77292aJiglioNero4 years ago220),
221);
222} else {
223throw ErrorHelper.getInternalError(
224InternalErrorCode.NgrokIsNotInstalledGlobally,
225ngrokPackageConfig.getVersion(true),
226);
227}
228}
efb436fcRedMickey5 years ago229}
230
231public removeNodeModulesPathFromEnvIfWasSet(): void {
232if (this.nodeModulesGlobalPathAddedToEnv) {
09f6024fHeniker4 years ago233delete process.env.NODE_MODULES;
efb436fcRedMickey5 years ago234this.nodeModulesGlobalPathAddedToEnv = false;
235}
236}
237
0d77292aJiglioNero4 years ago238public async addNodeModulesPathToEnvIfNotPresent(): Promise<void> {
09f6024fHeniker4 years ago239if (!process.env.NODE_MODULES) {
240process.env.NODE_MODULES = await getNodeModulesGlobalPath();
0d77292aJiglioNero4 years ago241this.nodeModulesGlobalPathAddedToEnv = true;
efb436fcRedMickey5 years ago242}
243}
244
866e020bRedMickey4 years ago245private async isBareWorkflowProject(): Promise<boolean> {
246const packageJson = await this.getAppPackageInformation();
247
248if (packageJson.dependencies && packageJson.dependencies.expokit) {
249return false;
250}
251if (packageJson.devDependencies && packageJson.devDependencies.expokit) {
252return false;
253}
254
255const xcodeprojFiles = globSync("ios/**/*.xcodeproj", {
256absolute: true,
257cwd: this.projectRootPath,
258});
259if (xcodeprojFiles.length) {
260return true;
261}
262const gradleFiles = globSync("android/**/*.gradle", {
263absolute: true,
264cwd: this.projectRootPath,
265});
266if (gradleFiles.length) {
267return true;
268}
269
270return false;
271}
272
efb436fcRedMickey5 years ago273private async getArgumentsFromExpoMetroConfig(projectRoot: string): Promise<ExpMetroConfig> {
0d77292aJiglioNero4 years ago274const config = await XDL.getMetroConfig(projectRoot);
275return { sourceExts: config.resolver.sourceExts };
db6fd42aRuslan Bikkinin7 years ago276}
277
1c32fe84Patricio Beltran9 years ago278/**
94cd5149Artem Egorov8 years ago279* Path to a given file inside the .vscode directory
1c32fe84Patricio Beltran9 years ago280*/
66412fdfRuslan Bikkinin7 years ago281private dotvscodePath(filename: string, isAbsolute: boolean): string {
282let paths = [".vscode", filename];
283if (isAbsolute) {
284paths = [this.workspaceRootPath].concat(...paths);
285}
286return path.join(...paths);
94cd5149Artem Egorov8 years ago287}
288
0d77292aJiglioNero4 years ago289private async createExpoEntry(name: string): Promise<void> {
290await this.lazilyInitialize();
291const entryPoint = await this.detectEntry();
292const content = this.generateFileContent(name, entryPoint);
293return await this.fs.writeFile(this.dotvscodePath(EXPONENT_INDEX, true), content);
94cd5149Artem Egorov8 years ago294}
1c32fe84Patricio Beltran9 years ago295
0d77292aJiglioNero4 years ago296private async detectEntry(): Promise<string> {
297await this.lazilyInitialize();
298const [expo, ios] = await Promise.all([
94cd5149Artem Egorov8 years ago299this.fs.exists(this.pathToFileInWorkspace(DEFAULT_EXPONENT_INDEX)),
300this.fs.exists(this.pathToFileInWorkspace(DEFAULT_IOS_INDEX)),
301this.fs.exists(this.pathToFileInWorkspace(DEFAULT_ANDROID_INDEX)),
0d77292aJiglioNero4 years ago302]);
303return expo
304? this.pathToFileInWorkspace(DEFAULT_EXPONENT_INDEX)
305: ios
306? this.pathToFileInWorkspace(DEFAULT_IOS_INDEX)
307: this.pathToFileInWorkspace(DEFAULT_ANDROID_INDEX);
94cd5149Artem Egorov8 years ago308}
1c32fe84Patricio Beltran9 years ago309
94cd5149Artem Egorov8 years ago310private generateFileContent(name: string, entryPoint: string): string {
311return `// This file is automatically generated by VS Code
312// Please do not modify it manually. All changes will be lost.
313var React = require('${this.pathToFileInWorkspace("/node_modules/react")}');
314var { Component } = React;
315var ReactNative = require('${this.pathToFileInWorkspace("/node_modules/react-native")}');
316var { AppRegistry } = ReactNative;
f6b41bbfAlexander Sorokin9 years ago317AppRegistry.registerRunnable('main', function(appParameters) {
94cd5149Artem Egorov8 years ago318AppRegistry.runApplication('${name}', appParameters);
253b6e8eRedMickey5 years ago319});
6a47f22aRedMickey4 years ago320require('${entryPoint}');`;
1c32fe84Patricio Beltran9 years ago321}
322
0d77292aJiglioNero4 years ago323private async patchAppJson(isExpo: boolean = true): Promise<void> {
324let appJson: AppJson;
325try {
326appJson = await this.readAppJson();
327} catch {
7888898eEzio Li3 years ago328// If app.json doesn't exist, we will create it
329logger.log("Cannot get existing app.json file. Create new one.");
0d77292aJiglioNero4 years ago330appJson = <AppJson>{};
331}
332const packageName = await this.getPackageName();
333
334const expoConfig = <ExpConfig>(appJson.expo || {});
335if (!expoConfig.name || !expoConfig.slug) {
336expoConfig.slug = expoConfig.slug || appJson.name || packageName.replace(" ", "-");
337expoConfig.name = expoConfig.name || appJson.name || packageName;
338appJson.expo = expoConfig;
339}
340
341if (!appJson.name) {
342appJson.name = packageName;
343}
344
345if (!appJson.expo.sdkVersion) {
346const sdkVersion = await this.exponentSdk(true);
347appJson.expo.sdkVersion = sdkVersion;
348}
349
350if (!isExpo) {
351// entryPoint must be relative
352// https://docs.expo.io/versions/latest/workflow/configuration/#entrypoint
353appJson.expo.entryPoint = this.dotvscodePath(EXPONENT_INDEX, false);
354}
355
356appJson = appJson ? await this.writeAppJson(appJson) : appJson;
357
358if (!isExpo) {
359await this.createExpoEntry(appJson.expo.name);
360}
27710197Vladimir Kotikov8 years ago361}
1c32fe84Patricio Beltran9 years ago362
363/**
364* Exponent sdk version that maps to the current react-native version
365* If react native version is not supported it returns null.
366*/
a1824f64Ezio Li2 years ago367public async exponentSdk(showProgress: boolean = false): Promise<string> {
94cd5149Artem Egorov8 years ago368if (showProgress) {
0a68f8dbArtem Egorov8 years ago369this.logger.logStream("...");
1c32fe84Patricio Beltran9 years ago370}
94cd5149Artem Egorov8 years ago371
0d77292aJiglioNero4 years ago372const versions = await ProjectVersionHelper.getReactNativeVersions(this.projectRootPath);
373if (showProgress) {
374this.logger.logStream(".");
375}
376const sdkVersion = await this.mapFacebookReactNativeVersionToExpoVersion(
377versions.reactNativeVersion,
378);
379if (!sdkVersion) {
380const supportedVersions = await this.getFacebookReactNativeVersions();
381throw ErrorHelper.getInternalError(
382InternalErrorCode.RNVersionNotSupportedByExponent,
383supportedVersions.join(", "),
384);
385}
386return sdkVersion;
1c32fe84Patricio Beltran9 years ago387}
388
0d77292aJiglioNero4 years ago389private async getFacebookReactNativeVersions(): Promise<string[]> {
390const sdkVersions = await XDL.getExpoSdkVersions();
391const facebookReactNativeVersions = new Set(
392Object.values(sdkVersions)
393.map(data => data.facebookReactNativeVersion)
394.filter(version => version),
395);
396return Array.from(facebookReactNativeVersions);
8f50947fRedMickey5 years ago397}
398
0d77292aJiglioNero4 years ago399private async mapFacebookReactNativeVersionToExpoVersion(
8f50947fRedMickey5 years ago400outerFacebookReactNativeVersion: string,
401): Promise<string | null> {
402if (!semver.valid(outerFacebookReactNativeVersion)) {
0d77292aJiglioNero4 years ago403throw new Error(
404`${outerFacebookReactNativeVersion} is not a valid version. It must be in the form of x.y.z`,
8f50947fRedMickey5 years ago405);
406}
407
0d77292aJiglioNero4 years ago408const sdkVersions = await XDL.getReleasedExpoSdkVersions();
409let currentSdkVersion: string | null = null;
410for (const [version, { facebookReactNativeVersion }] of Object.entries(sdkVersions)) {
411if (
412semver.major(outerFacebookReactNativeVersion) ===
413semver.major(facebookReactNativeVersion) &&
414semver.minor(outerFacebookReactNativeVersion) ===
415semver.minor(facebookReactNativeVersion) &&
416(!currentSdkVersion || semver.gt(version, currentSdkVersion))
417) {
418currentSdkVersion = version;
8f50947fRedMickey5 years ago419}
0d77292aJiglioNero4 years ago420}
421return currentSdkVersion;
8f50947fRedMickey5 years ago422}
94cd5149Artem Egorov8 years ago423
1c32fe84Patricio Beltran9 years ago424/**
94cd5149Artem Egorov8 years ago425* Name specified on user's package.json
1c32fe84Patricio Beltran9 years ago426*/
ce5e88eeYuri Skorokhodov5 years ago427private getPackageName(): Promise<string> {
94cd5149Artem Egorov8 years ago428return new Package(this.projectRootPath, { fileSystem: this.fs }).name();
429}
430
0d77292aJiglioNero4 years ago431private async getExpConfig(): Promise<ExpConfig> {
432try {
433return this.readExpJson();
434} catch (err) {
34472878RedMickey5 years ago435if (err.code === "ENOENT") {
0d77292aJiglioNero4 years ago436const appJson = await this.readAppJson();
437return appJson.expo || {};
34472878RedMickey5 years ago438}
0d77292aJiglioNero4 years ago439throw err;
440}
1c32fe84Patricio Beltran9 years ago441}
442
69305188EzioLi9 months ago443private async getFromExpConfig<K extends keyof ExpConfig>(key: K): Promise<ExpConfig[K]> {
0d77292aJiglioNero4 years ago444const config = await this.getExpConfig();
445return config[key];
1c32fe84Patricio Beltran9 years ago446}
447
448/**
94cd5149Artem Egorov8 years ago449* Returns the specified setting from exp.json if it exists
1c32fe84Patricio Beltran9 years ago450*/
0d77292aJiglioNero4 years ago451private async readExpJson(): Promise<ExpConfig> {
94cd5149Artem Egorov8 years ago452const expJsonPath = this.pathToFileInWorkspace(EXP_JSON);
dc94981bQuan Jin3 years ago453return this.fs.readFile(expJsonPath).then(content => {
454return stripJsonTrailingComma(content.toString());
455});
1c32fe84Patricio Beltran9 years ago456}
457
0d77292aJiglioNero4 years ago458private async readAppJson(): Promise<AppJson> {
94cd5149Artem Egorov8 years ago459const appJsonPath = this.pathToFileInWorkspace(APP_JSON);
7888898eEzio Li3 years ago460logger.log(`Getting app.json path: ${appJsonPath}`);
dc94981bQuan Jin3 years ago461return this.fs.readFile(appJsonPath).then(content => {
462return stripJsonTrailingComma(content.toString());
463});
1c32fe84Patricio Beltran9 years ago464}
465
0d77292aJiglioNero4 years ago466private async writeAppJson(config: AppJson): Promise<AppJson> {
94cd5149Artem Egorov8 years ago467const appJsonPath = this.pathToFileInWorkspace(APP_JSON);
0d77292aJiglioNero4 years ago468await this.fs.writeFile(appJsonPath, JSON.stringify(config, null, 2));
469return config;
1c32fe84Patricio Beltran9 years ago470}
471
ce5e88eeYuri Skorokhodov5 years ago472private getAppPackageInformation(): Promise<IPackageInformation> {
66412fdfRuslan Bikkinin7 years ago473return new Package(this.projectRootPath, { fileSystem: this.fs }).parsePackageInformation();
474}
475
1c32fe84Patricio Beltran9 years ago476/**
38edb09eAlexander Sorokin9 years ago477* Path to a given file from the workspace root
1c32fe84Patricio Beltran9 years ago478*/
479private pathToFileInWorkspace(filename: string): string {
94cd5149Artem Egorov8 years ago480return path.join(this.projectRootPath, filename).replace(DBL_SLASHES, "/");
1c32fe84Patricio Beltran9 years ago481}
482
a57e740bPatricio Beltran9 years ago483/**
dc94981bQuan Jin3 years ago484* Works as a constructor but only initializes when it's actually needed.
a57e740bPatricio Beltran9 years ago485*/
716f31d0JiglioNero5 years ago486private async lazilyInitialize(): Promise<void> {
a57e740bPatricio Beltran9 years ago487if (!this.hasInitialized) {
488this.hasInitialized = true;
716f31d0JiglioNero5 years ago489await this.preloadExponentDependency();
09f6024fHeniker4 years ago490void XDL.configReactNativeVersionWarnings();
491void XDL.attachLoggerStream(this.projectRootPath, {
a57e740bPatricio Beltran9 years ago492stream: {
493write: (chunk: any) => {
494if (chunk.level <= 30) {
0a68f8dbArtem Egorov8 years ago495this.logger.logStream(chunk.msg);
3cf8f692Ezio Li3 years ago496this.logger.logStream("\n");
a57e740bPatricio Beltran9 years ago497} else if (chunk.level === 40) {
0a68f8dbArtem Egorov8 years ago498this.logger.warning(chunk.msg);
a57e740bPatricio Beltran9 years ago499} else {
0a68f8dbArtem Egorov8 years ago500this.logger.error(chunk.msg);
a57e740bPatricio Beltran9 years ago501}
502},
503},
504type: "raw",
505});
506}
507}
57fee98eEzio Li3 years ago508
509public async getExpoEasProjectOwner(): Promise<string | null> {
510const appJsonPath = this.pathToFileInWorkspace(APP_JSON);
511try {
512return JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.owner == undefined
513? null
514: JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.owner;
515} catch {
516return null;
517}
518}
519
520public async getExpoEasProjectId(): Promise<string | null> {
521const appJsonPath = this.pathToFileInWorkspace(APP_JSON);
522try {
523return JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.extra.eas.projectId ==
524undefined
525? null
526: JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.extra.eas.projectId;
527} catch {
528return null;
529}
530}
531
532public async getExpoEasProjectName(): Promise<string | null> {
533const appJsonPath = this.pathToFileInWorkspace(APP_JSON);
534try {
535return JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.name == undefined
536? null
537: JSON.parse(fs.readFileSync(appJsonPath, "utf-8")).expo.name;
538} catch {
539return null;
540}
541}
5c8365a6Artem Egorov8 years ago542}