@expo/cli 0.3.1 → 0.4.0
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 +48 -10
- package/build/bin/cli +2 -2
- package/build/src/api/graphql/client.js +3 -1
- package/build/src/api/graphql/client.js.map +1 -1
- package/build/src/api/rest/client.js +5 -2
- package/build/src/api/rest/client.js.map +1 -1
- package/build/src/api/rest/wrapFetchWithProxy.js +25 -0
- package/build/src/api/rest/wrapFetchWithProxy.js.map +1 -0
- package/build/src/api/user/user.js +3 -1
- package/build/src/api/user/user.js.map +1 -1
- package/build/src/export/fork-bundleAsync.js +2 -1
- package/build/src/export/fork-bundleAsync.js.map +1 -1
- package/build/src/install/resolveOptions.js +6 -2
- package/build/src/install/resolveOptions.js.map +1 -1
- package/build/src/prebuild/copyTemplateFiles.js +6 -33
- package/build/src/prebuild/copyTemplateFiles.js.map +1 -1
- package/build/src/prebuild/resolveTemplate.js +2 -2
- package/build/src/prebuild/resolveTemplate.js.map +1 -1
- package/build/src/prebuild/updateFromTemplate.js +1 -3
- package/build/src/prebuild/updateFromTemplate.js.map +1 -1
- package/build/src/prebuild/updatePackageJson.js +3 -46
- package/build/src/prebuild/updatePackageJson.js.map +1 -1
- package/build/src/run/ios/XcodeBuild.js +2 -1
- package/build/src/run/ios/XcodeBuild.js.map +1 -1
- package/build/src/run/ios/codeSigning/simulatorCodeSigning.js +45 -0
- package/build/src/run/ios/codeSigning/simulatorCodeSigning.js.map +1 -0
- package/build/src/start/doctor/dependencies/validateDependenciesVersions.js +5 -0
- package/build/src/start/doctor/dependencies/validateDependenciesVersions.js.map +1 -1
- package/build/src/start/doctor/ngrok/NgrokResolver.js +5 -0
- package/build/src/start/doctor/ngrok/NgrokResolver.js.map +1 -1
- package/build/src/start/platforms/ExpoGoInstaller.js +8 -0
- package/build/src/start/platforms/ExpoGoInstaller.js.map +1 -1
- package/build/src/start/platforms/PlatformManager.js +6 -1
- package/build/src/start/platforms/PlatformManager.js.map +1 -1
- package/build/src/start/platforms/android/adbReverse.js +10 -0
- package/build/src/start/platforms/android/adbReverse.js.map +1 -1
- package/build/src/start/resolveOptions.js +1 -1
- package/build/src/start/resolveOptions.js.map +1 -1
- package/build/src/start/server/AsyncNgrok.js +58 -14
- package/build/src/start/server/AsyncNgrok.js.map +1 -1
- package/build/src/start/server/BundlerDevServer.js +18 -2
- package/build/src/start/server/BundlerDevServer.js.map +1 -1
- package/build/src/start/server/DevelopmentSession.js +26 -25
- package/build/src/start/server/DevelopmentSession.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +20 -5
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +1 -6
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js +36 -5
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/middleware/ClassicManifestMiddleware.js +4 -2
- package/build/src/start/server/middleware/ClassicManifestMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js +7 -3
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/RuntimeRedirectMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/resolveEntryPoint.js +2 -1
- package/build/src/start/server/middleware/resolveEntryPoint.js.map +1 -1
- package/build/src/start/server/middleware/resolvePlatform.js +3 -2
- package/build/src/start/server/middleware/resolvePlatform.js.map +1 -1
- package/build/src/start/server/webpack/WebpackBundlerDevServer.js +2 -8
- package/build/src/start/server/webpack/WebpackBundlerDevServer.js.map +1 -1
- package/build/src/utils/analytics/rudderstackClient.js +2 -2
- package/build/src/utils/codesigning.js +3 -0
- package/build/src/utils/codesigning.js.map +1 -1
- package/build/src/utils/downloadAppAsync.js +1 -2
- package/build/src/utils/downloadAppAsync.js.map +1 -1
- package/build/src/utils/env.js +37 -1
- package/build/src/utils/env.js.map +1 -1
- package/build/src/utils/npm.js +4 -11
- package/build/src/utils/npm.js.map +1 -1
- package/build/src/utils/url.js +2 -2
- package/build/src/utils/url.js.map +1 -1
- package/build/src/utils/validateApplicationId.js +3 -3
- package/build/src/utils/validateApplicationId.js.map +1 -1
- package/build/src/utils/variadic.js +18 -0
- package/build/src/utils/variadic.js.map +1 -1
- package/package.json +5 -4
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
exports.isNgrokClientError = isNgrokClientError;
|
|
5
6
|
var _externalModule = require("./ExternalModule");
|
|
6
7
|
class NgrokResolver extends _externalModule.ExternalModule {
|
|
7
8
|
constructor(projectRoot){
|
|
@@ -13,5 +14,9 @@ class NgrokResolver extends _externalModule.ExternalModule {
|
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
exports.NgrokResolver = NgrokResolver;
|
|
17
|
+
function isNgrokClientError(error) {
|
|
18
|
+
var ref;
|
|
19
|
+
return error == null ? void 0 : (ref = error.body) == null ? void 0 : ref.msg;
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
//# sourceMappingURL=NgrokResolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/doctor/ngrok/NgrokResolver.ts"],"sourcesContent":["import { ExternalModule } from './ExternalModule';\n\nexport interface NgrokOptions {\n authtoken?: string;\n port?: string | number | null;\n host?: string;\n httpauth?: string;\n region?: string;\n configPath?: string;\n\n proto?: 'http' | 'tcp' | 'tls';\n addr?: string;\n inspect?: boolean;\n auth?: string;\n host_header?: string;\n bind_tls?: true | false | 'both';\n subdomain?: string;\n hostname?: string;\n crt?: string;\n key?: string;\n client_cas?: string;\n remote_addr?: string;\n}\n\nexport interface NgrokInstance {\n getActiveProcess(): { pid: number };\n connect(\n props: {\n hostname
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/doctor/ngrok/NgrokResolver.ts"],"sourcesContent":["import { ExternalModule } from './ExternalModule';\n\nexport interface NgrokClientError {\n body: {\n error_code: number;\n status_code: number;\n msg: string;\n details: {\n err: string;\n };\n };\n}\n\nexport interface NgrokOptions {\n authtoken?: string;\n port?: string | number | null;\n host?: string;\n httpauth?: string;\n region?: string;\n configPath?: string;\n\n proto?: 'http' | 'tcp' | 'tls';\n addr?: string;\n inspect?: boolean;\n auth?: string;\n host_header?: string;\n bind_tls?: true | false | 'both';\n subdomain?: string;\n hostname?: string;\n crt?: string;\n key?: string;\n client_cas?: string;\n remote_addr?: string;\n}\n\nexport interface NgrokInstance {\n getActiveProcess(): { pid: number };\n connect(\n props: {\n hostname?: string;\n configPath: string;\n onStatusChange: (status: string) => void;\n } & NgrokOptions\n ): Promise<string>;\n kill(): Promise<void>;\n}\n\n/** Resolves the ngrok instance from local or globally installed package. */\nexport class NgrokResolver extends ExternalModule<NgrokInstance> {\n constructor(projectRoot: string) {\n super(\n projectRoot,\n {\n name: '@expo/ngrok',\n versionRange: '^4.1.0',\n },\n (packageName) =>\n `The package ${packageName} is required to use tunnels, would you like to install it globally?`\n );\n }\n}\n\nexport function isNgrokClientError(error: any): error is NgrokClientError {\n return error?.body?.msg;\n}\n"],"names":["isNgrokClientError","NgrokResolver","ExternalModule","constructor","projectRoot","name","versionRange","packageName","error","body","msg"],"mappings":"AAAA;;;;QA8DgBA,kBAAkB,GAAlBA,kBAAkB;AA9DH,IAAA,eAAkB,WAAlB,kBAAkB,CAAA;AAgD1C,MAAMC,aAAa,SAASC,eAAc,eAAA;IAC/CC,YAAYC,WAAmB,CAAE;QAC/B,KAAK,CACHA,WAAW,EACX;YACEC,IAAI,EAAE,aAAa;YACnBC,YAAY,EAAE,QAAQ;SACvB,EACD,CAACC,WAAW,GACV,CAAC,YAAY,EAAEA,WAAW,CAAC,mEAAmE,CAAC;QAAA,CAClG,CAAC;KACH;CACF;QAZYN,aAAa,GAAbA,aAAa;AAcnB,SAASD,kBAAkB,CAACQ,KAAU,EAA6B;QACjEA,GAAW;IAAlB,OAAOA,KAAK,QAAM,GAAXA,KAAAA,CAAW,GAAXA,CAAAA,GAAW,GAAXA,KAAK,CAAEC,IAAI,SAAA,GAAXD,KAAAA,CAAW,GAAXA,GAAW,CAAEE,GAAG,AAAL,CAAM;CACzB"}
|
|
@@ -4,8 +4,10 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
});
|
|
5
5
|
var _semver = _interopRequireDefault(require("semver"));
|
|
6
6
|
var _getVersions = require("../../api/getVersions");
|
|
7
|
+
var _settings = require("../../api/settings");
|
|
7
8
|
var Log = _interopRequireWildcard(require("../../log"));
|
|
8
9
|
var _downloadExpoGoAsync = require("../../utils/downloadExpoGoAsync");
|
|
10
|
+
var _errors = require("../../utils/errors");
|
|
9
11
|
var _ora = require("../../utils/ora");
|
|
10
12
|
var _prompts = require("../../utils/prompts");
|
|
11
13
|
function _interopRequireDefault(obj) {
|
|
@@ -88,6 +90,12 @@ class ExpoGoInstaller {
|
|
|
88
90
|
}
|
|
89
91
|
/** Check if a given device has Expo Go installed, if not then download and install it. */ async ensureAsync(deviceManager) {
|
|
90
92
|
let shouldInstall = !await deviceManager.isAppInstalledAsync(this.appId);
|
|
93
|
+
if (_settings.APISettings.isOffline && !shouldInstall) {
|
|
94
|
+
Log.warn(`Skipping Expo Go version validation in offline mode`);
|
|
95
|
+
return false;
|
|
96
|
+
} else if (_settings.APISettings.isOffline && shouldInstall) {
|
|
97
|
+
throw new _errors.CommandError("NO_EXPO_GO", `Expo Go is not installed on device "${deviceManager.name}", while running in offline mode. Manually install Expo Go or run without --offline flag.`);
|
|
98
|
+
}
|
|
91
99
|
if (!shouldInstall) {
|
|
92
100
|
shouldInstall = await this.uninstallExpoGoIfOutdatedAsync(deviceManager);
|
|
93
101
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/start/platforms/ExpoGoInstaller.ts"],"sourcesContent":["import semver from 'semver';\n\nimport { getVersionsAsync } from '../../api/getVersions';\nimport * as Log from '../../log';\nimport { downloadExpoGoAsync } from '../../utils/downloadExpoGoAsync';\nimport { logNewSection } from '../../utils/ora';\nimport { confirmAsync } from '../../utils/prompts';\nimport type { DeviceManager } from './DeviceManager';\n\nconst debug = require('debug')('expo:utils:ExpoGoInstaller') as typeof console.log;\n\n/** Given a platform, appId, and sdkVersion, this module will ensure that Expo Go is up-to-date on the provided device. */\nexport class ExpoGoInstaller<IDevice> {\n // Keep a list of [platform-deviceId] so we can prevent asking multiple times if a user wants to upgrade.\n // This can prevent annoying interactions when they don't want to upgrade for whatever reason.\n static cache: Record<string, boolean> = {};\n\n constructor(\n private platform: 'ios' | 'android',\n // Ultimately this should be inlined since we know the platform.\n private appId: string,\n private sdkVersion?: string\n ) {}\n\n /** Returns true if the installed app matching the previously provided `appId` is outdated. */\n async isClientOutdatedAsync(device: DeviceManager<IDevice>): Promise<boolean> {\n const installedVersion = await device.getAppVersionAsync(this.appId);\n if (!installedVersion) {\n return true;\n }\n const version = await this._getExpectedClientVersionAsync();\n debug(`Expected Expo Go version: ${version}, installed version: ${installedVersion}`);\n return version ? !semver.eq(installedVersion, version) : true;\n }\n\n /** Returns the expected version of Expo Go given the project SDK Version. Exposed for testing. */\n async _getExpectedClientVersionAsync(): Promise<string | null> {\n const versions = await getVersionsAsync();\n // Like `sdkVersions['44.0.0']['androidClientVersion'] = '1.0.0'`\n const specificVersion =\n versions?.sdkVersions?.[this.sdkVersion!]?.[`${this.platform}ClientVersion`];\n const latestVersion = versions[`${this.platform}Version`];\n return specificVersion ?? latestVersion ?? null;\n }\n\n /** Returns a boolean indicating if Expo Go should be installed. Returns `true` if the app was uninstalled. */\n async uninstallExpoGoIfOutdatedAsync(deviceManager: DeviceManager<IDevice>): Promise<boolean> {\n const cacheId = `${this.platform}-${deviceManager.identifier}`;\n\n if (ExpoGoInstaller.cache[cacheId]) {\n debug('skipping subsequent upgrade check');\n return false;\n }\n ExpoGoInstaller.cache[cacheId] = true;\n if (await this.isClientOutdatedAsync(deviceManager)) {\n // Only prompt once per device, per run.\n const confirm = await confirmAsync({\n initial: true,\n message: `Expo Go on ${deviceManager.name} is outdated, would you like to upgrade?`,\n });\n if (confirm) {\n // Don't need to uninstall to update on iOS.\n if (this.platform !== 'ios') {\n Log.log(`Uninstalling Expo Go from ${this.platform} device ${deviceManager.name}.`);\n await deviceManager.uninstallAppAsync(this.appId);\n }\n return true;\n }\n }\n return false;\n }\n\n /** Check if a given device has Expo Go installed, if not then download and install it. */\n async ensureAsync(deviceManager: DeviceManager<IDevice>): Promise<boolean> {\n let shouldInstall = !(await deviceManager.isAppInstalledAsync(this.appId));\n\n if (!shouldInstall) {\n shouldInstall = await this.uninstallExpoGoIfOutdatedAsync(deviceManager);\n }\n\n if (shouldInstall) {\n // Download the Expo Go app from the Expo servers.\n const binaryPath = await downloadExpoGoAsync(this.platform, { sdkVersion: this.sdkVersion });\n // Install the app on the device.\n const ora = logNewSection(`Installing Expo Go on ${deviceManager.name}`);\n try {\n await deviceManager.installAppAsync(binaryPath);\n } finally {\n ora.stop();\n }\n return true;\n }\n return false;\n }\n}\n"],"names":["Log","debug","require","ExpoGoInstaller","cache","constructor","platform","appId","sdkVersion","isClientOutdatedAsync","device","installedVersion","getAppVersionAsync","version","_getExpectedClientVersionAsync","semver","eq","versions","getVersionsAsync","specificVersion","sdkVersions","latestVersion","uninstallExpoGoIfOutdatedAsync","deviceManager","cacheId","identifier","confirm","confirmAsync","initial","message","name","log","uninstallAppAsync","ensureAsync","shouldInstall","isAppInstalledAsync","binaryPath","downloadExpoGoAsync","ora","logNewSection","installAppAsync","stop"],"mappings":"AAAA;;;;AAAmB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AAEM,IAAA,YAAuB,WAAvB,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"sources":["../../../../src/start/platforms/ExpoGoInstaller.ts"],"sourcesContent":["import semver from 'semver';\n\nimport { getVersionsAsync } from '../../api/getVersions';\nimport { APISettings } from '../../api/settings';\nimport * as Log from '../../log';\nimport { downloadExpoGoAsync } from '../../utils/downloadExpoGoAsync';\nimport { CommandError } from '../../utils/errors';\nimport { logNewSection } from '../../utils/ora';\nimport { confirmAsync } from '../../utils/prompts';\nimport type { DeviceManager } from './DeviceManager';\n\nconst debug = require('debug')('expo:utils:ExpoGoInstaller') as typeof console.log;\n\n/** Given a platform, appId, and sdkVersion, this module will ensure that Expo Go is up-to-date on the provided device. */\nexport class ExpoGoInstaller<IDevice> {\n // Keep a list of [platform-deviceId] so we can prevent asking multiple times if a user wants to upgrade.\n // This can prevent annoying interactions when they don't want to upgrade for whatever reason.\n static cache: Record<string, boolean> = {};\n\n constructor(\n private platform: 'ios' | 'android',\n // Ultimately this should be inlined since we know the platform.\n private appId: string,\n private sdkVersion?: string\n ) {}\n\n /** Returns true if the installed app matching the previously provided `appId` is outdated. */\n async isClientOutdatedAsync(device: DeviceManager<IDevice>): Promise<boolean> {\n const installedVersion = await device.getAppVersionAsync(this.appId);\n if (!installedVersion) {\n return true;\n }\n const version = await this._getExpectedClientVersionAsync();\n debug(`Expected Expo Go version: ${version}, installed version: ${installedVersion}`);\n return version ? !semver.eq(installedVersion, version) : true;\n }\n\n /** Returns the expected version of Expo Go given the project SDK Version. Exposed for testing. */\n async _getExpectedClientVersionAsync(): Promise<string | null> {\n const versions = await getVersionsAsync();\n // Like `sdkVersions['44.0.0']['androidClientVersion'] = '1.0.0'`\n const specificVersion =\n versions?.sdkVersions?.[this.sdkVersion!]?.[`${this.platform}ClientVersion`];\n const latestVersion = versions[`${this.platform}Version`];\n return specificVersion ?? latestVersion ?? null;\n }\n\n /** Returns a boolean indicating if Expo Go should be installed. Returns `true` if the app was uninstalled. */\n async uninstallExpoGoIfOutdatedAsync(deviceManager: DeviceManager<IDevice>): Promise<boolean> {\n const cacheId = `${this.platform}-${deviceManager.identifier}`;\n\n if (ExpoGoInstaller.cache[cacheId]) {\n debug('skipping subsequent upgrade check');\n return false;\n }\n ExpoGoInstaller.cache[cacheId] = true;\n if (await this.isClientOutdatedAsync(deviceManager)) {\n // Only prompt once per device, per run.\n const confirm = await confirmAsync({\n initial: true,\n message: `Expo Go on ${deviceManager.name} is outdated, would you like to upgrade?`,\n });\n if (confirm) {\n // Don't need to uninstall to update on iOS.\n if (this.platform !== 'ios') {\n Log.log(`Uninstalling Expo Go from ${this.platform} device ${deviceManager.name}.`);\n await deviceManager.uninstallAppAsync(this.appId);\n }\n return true;\n }\n }\n return false;\n }\n\n /** Check if a given device has Expo Go installed, if not then download and install it. */\n async ensureAsync(deviceManager: DeviceManager<IDevice>): Promise<boolean> {\n let shouldInstall = !(await deviceManager.isAppInstalledAsync(this.appId));\n\n if (APISettings.isOffline && !shouldInstall) {\n Log.warn(`Skipping Expo Go version validation in offline mode`);\n return false;\n } else if (APISettings.isOffline && shouldInstall) {\n throw new CommandError(\n 'NO_EXPO_GO',\n `Expo Go is not installed on device \"${deviceManager.name}\", while running in offline mode. Manually install Expo Go or run without --offline flag.`\n );\n }\n\n if (!shouldInstall) {\n shouldInstall = await this.uninstallExpoGoIfOutdatedAsync(deviceManager);\n }\n\n if (shouldInstall) {\n // Download the Expo Go app from the Expo servers.\n const binaryPath = await downloadExpoGoAsync(this.platform, { sdkVersion: this.sdkVersion });\n // Install the app on the device.\n const ora = logNewSection(`Installing Expo Go on ${deviceManager.name}`);\n try {\n await deviceManager.installAppAsync(binaryPath);\n } finally {\n ora.stop();\n }\n return true;\n }\n return false;\n }\n}\n"],"names":["Log","debug","require","ExpoGoInstaller","cache","constructor","platform","appId","sdkVersion","isClientOutdatedAsync","device","installedVersion","getAppVersionAsync","version","_getExpectedClientVersionAsync","semver","eq","versions","getVersionsAsync","specificVersion","sdkVersions","latestVersion","uninstallExpoGoIfOutdatedAsync","deviceManager","cacheId","identifier","confirm","confirmAsync","initial","message","name","log","uninstallAppAsync","ensureAsync","shouldInstall","isAppInstalledAsync","APISettings","isOffline","warn","CommandError","binaryPath","downloadExpoGoAsync","ora","logNewSection","installAppAsync","stop"],"mappings":"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"}
|
|
@@ -32,7 +32,12 @@ class PlatformManager {
|
|
|
32
32
|
const redirectUrl = this.props.getRedirectUrl();
|
|
33
33
|
if (redirectUrl) {
|
|
34
34
|
// If the redirect page feature is enabled, check if the project has a resolvable native identifier.
|
|
35
|
-
|
|
35
|
+
let applicationId;
|
|
36
|
+
try {
|
|
37
|
+
applicationId = await this._getAppIdResolver().getAppIdAsync();
|
|
38
|
+
} catch {
|
|
39
|
+
_log.Log.warn(_chalk.default`\u203A Launching in Expo Go. If you want to use a ` + `development build, you need to create and install one first, or, if you already ` + _chalk.default`have a build, add {bold ios.bundleIdentifier} and {bold android.package} to ` + `this project's app config.\n${(0, _link).learnMore("https://docs.expo.dev/development/build/")}`);
|
|
40
|
+
}
|
|
36
41
|
if (applicationId) {
|
|
37
42
|
debug(`Resolving launch URL: (appId: ${applicationId}, redirect URL: ${redirectUrl})`);
|
|
38
43
|
// NOTE(EvanBacon): This adds considerable amount of time to the command, we should consider removing or memoizing it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/start/platforms/PlatformManager.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport assert from 'assert';\nimport chalk from 'chalk';\n\nimport { Log } from '../../log';\nimport { logEventAsync } from '../../utils/analytics/rudderstackClient';\nimport { CommandError, UnimplementedError } from '../../utils/errors';\nimport { learnMore } from '../../utils/link';\nimport { AppIdResolver } from './AppIdResolver';\nimport { DeviceManager } from './DeviceManager';\n\nconst debug = require('debug')('expo:start:platforms:platformManager') as typeof console.log;\n\nexport interface BaseOpenInCustomProps {\n scheme?: string;\n applicationId?: string | null;\n}\n\nexport interface BaseResolveDeviceProps<IDevice> {\n /** Should prompt the user to select a device. */\n shouldPrompt?: boolean;\n /** The target device to use. */\n device?: IDevice;\n}\n\n/** An abstract class for launching a URL on a device. */\nexport class PlatformManager<\n IDevice,\n IOpenInCustomProps extends BaseOpenInCustomProps = BaseOpenInCustomProps,\n IResolveDeviceProps extends BaseResolveDeviceProps<IDevice> = BaseResolveDeviceProps<IDevice>\n> {\n constructor(\n protected projectRoot: string,\n protected props: {\n platform: 'ios' | 'android';\n /** Get the base URL for the dev server hosting this platform manager. */\n getDevServerUrl: () => string | null;\n /** Expo Go URL. */\n getExpoGoUrl: () => string;\n /**\n * Get redirect URL for native disambiguation.\n * @returns a URL like `http://localhost:19000/_expo/loading`\n */\n getRedirectUrl: () => string | null;\n /** Dev Client */\n getCustomRuntimeUrl: (props?: { scheme?: string }) => string | null;\n /** Resolve a device, this function should automatically handle opening the device and asserting any system validations. */\n resolveDeviceAsync: (\n resolver?: Partial<IResolveDeviceProps>\n ) => Promise<DeviceManager<IDevice>>;\n }\n ) {}\n\n /** Returns the project application identifier or asserts that one is not defined. Exposed for testing. */\n _getAppIdResolver(): AppIdResolver {\n throw new UnimplementedError();\n }\n\n /**\n * Get the URL for users intending to launch the project in Expo Go.\n * The CLI will check if the project has a custom dev client and if the redirect page feature is enabled.\n * If both are true, the CLI will return the redirect page URL.\n */\n protected async getExpoGoOrCustomRuntimeUrlAsync(\n deviceManager: DeviceManager<IDevice>\n ): Promise<string> {\n // Determine if the redirect page feature is enabled first since it's the cheapest to check.\n const redirectUrl = this.props.getRedirectUrl();\n if (redirectUrl) {\n // If the redirect page feature is enabled, check if the project has a resolvable native identifier.\n const applicationId = await this._getAppIdResolver().getAppIdAsync();\n if (applicationId) {\n debug(`Resolving launch URL: (appId: ${applicationId}, redirect URL: ${redirectUrl})`);\n // NOTE(EvanBacon): This adds considerable amount of time to the command, we should consider removing or memoizing it.\n // Finally determine if the target device has a custom dev client installed.\n if (await deviceManager.isAppInstalledAsync(applicationId)) {\n return redirectUrl;\n } else {\n // Log a warning if no development build is available on the device, but the\n // interstitial page would otherwise be opened.\n Log.warn(\n chalk`\\u203A The {bold expo-dev-client} package is installed, but a development build is not ` +\n chalk`installed on {bold ${deviceManager.name}}.\\nLaunching in Expo Go. If you want to use a ` +\n `development build, you need to create and install one first.\\n${learnMore(\n 'https://docs.expo.dev/development/build/'\n )}`\n );\n }\n }\n }\n\n return this.props.getExpoGoUrl();\n }\n\n protected async openProjectInExpoGoAsync(\n resolveSettings: Partial<IResolveDeviceProps> = {}\n ): Promise<{ url: string }> {\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n const url = await this.getExpoGoOrCustomRuntimeUrlAsync(deviceManager);\n\n deviceManager.logOpeningUrl(url);\n\n // TODO: Expensive, we should only do this once.\n const { exp } = getConfig(this.projectRoot);\n const installedExpo = await deviceManager.ensureExpoGoAsync(exp.sdkVersion);\n\n deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n await logEventAsync('Open Url on Device', {\n platform: this.props.platform,\n installedExpo,\n });\n\n return { url };\n }\n\n private async openProjectInCustomRuntimeAsync(\n resolveSettings: Partial<IResolveDeviceProps> = {},\n props: Partial<IOpenInCustomProps> = {}\n ): Promise<{ url: string }> {\n debug(\n `open custom (${Object.entries(props)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ')})`\n );\n\n let url = this.props.getCustomRuntimeUrl({ scheme: props.scheme });\n debug(`Opening project in custom runtime: ${url} -- %O`, props);\n // TODO: It's unclear why we do application id validation when opening with a URL\n const applicationId = props.applicationId ?? (await this._getAppIdResolver().getAppIdAsync());\n\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n\n if (!(await deviceManager.isAppInstalledAsync(applicationId))) {\n throw new CommandError(\n `No development build (${applicationId}) for this project is installed. ` +\n `Please make and install a development build on the device first.\\n${learnMore(\n 'https://docs.expo.dev/development/build/'\n )}`\n );\n }\n\n // TODO: Rethink analytics\n await logEventAsync('Open Url on Device', {\n platform: this.props.platform,\n installedExpo: false,\n });\n\n if (!url) {\n url = this._resolveAlternativeLaunchUrl(applicationId, props);\n }\n\n deviceManager.logOpeningUrl(url);\n await deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n return {\n url,\n };\n }\n\n /** Launch the project on a device given the input runtime. */\n async openAsync(\n options:\n | {\n runtime: 'expo' | 'web';\n }\n | {\n runtime: 'custom';\n props?: Partial<IOpenInCustomProps>;\n },\n resolveSettings: Partial<IResolveDeviceProps> = {}\n ): Promise<{ url: string }> {\n debug(\n `open (runtime: ${options.runtime}, platform: ${this.props.platform}, device: %O, shouldPrompt: ${resolveSettings.shouldPrompt})`,\n resolveSettings.device\n );\n if (options.runtime === 'expo') {\n return this.openProjectInExpoGoAsync(resolveSettings);\n } else if (options.runtime === 'web') {\n return this.openWebProjectAsync(resolveSettings);\n } else if (options.runtime === 'custom') {\n return this.openProjectInCustomRuntimeAsync(resolveSettings, options.props);\n } else {\n throw new CommandError(`Invalid runtime target: ${options.runtime}`);\n }\n }\n\n /** Open the current web project (Webpack) in a device . */\n private async openWebProjectAsync(resolveSettings: Partial<IResolveDeviceProps> = {}): Promise<{\n url: string;\n }> {\n const url = this.props.getDevServerUrl();\n assert(url, 'Dev server is not running.');\n\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n deviceManager.logOpeningUrl(url);\n await deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n return { url };\n }\n\n /** If the launch URL cannot be determined (`custom` runtimes) then an alternative string can be provided to open the device. Often a device ID or activity to launch. Exposed for testing. */\n _resolveAlternativeLaunchUrl(\n applicationId: string,\n props: Partial<IOpenInCustomProps> = {}\n ): string {\n throw new UnimplementedError();\n }\n}\n"],"names":["debug","require","PlatformManager","constructor","projectRoot","props","_getAppIdResolver","UnimplementedError","getExpoGoOrCustomRuntimeUrlAsync","deviceManager","redirectUrl","getRedirectUrl","applicationId","getAppIdAsync","isAppInstalledAsync","Log","warn","chalk","name","learnMore","getExpoGoUrl","openProjectInExpoGoAsync","resolveSettings","resolveDeviceAsync","url","logOpeningUrl","exp","getConfig","installedExpo","ensureExpoGoAsync","sdkVersion","activateWindowAsync","openUrlAsync","logEventAsync","platform","openProjectInCustomRuntimeAsync","Object","entries","map","k","v","join","getCustomRuntimeUrl","scheme","CommandError","_resolveAlternativeLaunchUrl","openAsync","options","runtime","shouldPrompt","device","openWebProjectAsync","getDevServerUrl","assert"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/start/platforms/PlatformManager.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport assert from 'assert';\nimport chalk from 'chalk';\n\nimport { Log } from '../../log';\nimport { logEventAsync } from '../../utils/analytics/rudderstackClient';\nimport { CommandError, UnimplementedError } from '../../utils/errors';\nimport { learnMore } from '../../utils/link';\nimport { AppIdResolver } from './AppIdResolver';\nimport { DeviceManager } from './DeviceManager';\n\nconst debug = require('debug')('expo:start:platforms:platformManager') as typeof console.log;\n\nexport interface BaseOpenInCustomProps {\n scheme?: string;\n applicationId?: string | null;\n}\n\nexport interface BaseResolveDeviceProps<IDevice> {\n /** Should prompt the user to select a device. */\n shouldPrompt?: boolean;\n /** The target device to use. */\n device?: IDevice;\n}\n\n/** An abstract class for launching a URL on a device. */\nexport class PlatformManager<\n IDevice,\n IOpenInCustomProps extends BaseOpenInCustomProps = BaseOpenInCustomProps,\n IResolveDeviceProps extends BaseResolveDeviceProps<IDevice> = BaseResolveDeviceProps<IDevice>\n> {\n constructor(\n protected projectRoot: string,\n protected props: {\n platform: 'ios' | 'android';\n /** Get the base URL for the dev server hosting this platform manager. */\n getDevServerUrl: () => string | null;\n /** Expo Go URL. */\n getExpoGoUrl: () => string;\n /**\n * Get redirect URL for native disambiguation.\n * @returns a URL like `http://localhost:19000/_expo/loading`\n */\n getRedirectUrl: () => string | null;\n /** Dev Client */\n getCustomRuntimeUrl: (props?: { scheme?: string }) => string | null;\n /** Resolve a device, this function should automatically handle opening the device and asserting any system validations. */\n resolveDeviceAsync: (\n resolver?: Partial<IResolveDeviceProps>\n ) => Promise<DeviceManager<IDevice>>;\n }\n ) {}\n\n /** Returns the project application identifier or asserts that one is not defined. Exposed for testing. */\n _getAppIdResolver(): AppIdResolver {\n throw new UnimplementedError();\n }\n\n /**\n * Get the URL for users intending to launch the project in Expo Go.\n * The CLI will check if the project has a custom dev client and if the redirect page feature is enabled.\n * If both are true, the CLI will return the redirect page URL.\n */\n protected async getExpoGoOrCustomRuntimeUrlAsync(\n deviceManager: DeviceManager<IDevice>\n ): Promise<string> {\n // Determine if the redirect page feature is enabled first since it's the cheapest to check.\n const redirectUrl = this.props.getRedirectUrl();\n if (redirectUrl) {\n // If the redirect page feature is enabled, check if the project has a resolvable native identifier.\n let applicationId;\n try {\n applicationId = await this._getAppIdResolver().getAppIdAsync();\n } catch {\n Log.warn(\n chalk`\\u203A Launching in Expo Go. If you want to use a ` +\n `development build, you need to create and install one first, or, if you already ` +\n chalk`have a build, add {bold ios.bundleIdentifier} and {bold android.package} to ` +\n `this project's app config.\\n${learnMore('https://docs.expo.dev/development/build/')}`\n );\n }\n if (applicationId) {\n debug(`Resolving launch URL: (appId: ${applicationId}, redirect URL: ${redirectUrl})`);\n // NOTE(EvanBacon): This adds considerable amount of time to the command, we should consider removing or memoizing it.\n // Finally determine if the target device has a custom dev client installed.\n if (await deviceManager.isAppInstalledAsync(applicationId)) {\n return redirectUrl;\n } else {\n // Log a warning if no development build is available on the device, but the\n // interstitial page would otherwise be opened.\n Log.warn(\n chalk`\\u203A The {bold expo-dev-client} package is installed, but a development build is not ` +\n chalk`installed on {bold ${deviceManager.name}}.\\nLaunching in Expo Go. If you want to use a ` +\n `development build, you need to create and install one first.\\n${learnMore(\n 'https://docs.expo.dev/development/build/'\n )}`\n );\n }\n }\n }\n\n return this.props.getExpoGoUrl();\n }\n\n protected async openProjectInExpoGoAsync(\n resolveSettings: Partial<IResolveDeviceProps> = {}\n ): Promise<{ url: string }> {\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n const url = await this.getExpoGoOrCustomRuntimeUrlAsync(deviceManager);\n\n deviceManager.logOpeningUrl(url);\n\n // TODO: Expensive, we should only do this once.\n const { exp } = getConfig(this.projectRoot);\n const installedExpo = await deviceManager.ensureExpoGoAsync(exp.sdkVersion);\n\n deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n await logEventAsync('Open Url on Device', {\n platform: this.props.platform,\n installedExpo,\n });\n\n return { url };\n }\n\n private async openProjectInCustomRuntimeAsync(\n resolveSettings: Partial<IResolveDeviceProps> = {},\n props: Partial<IOpenInCustomProps> = {}\n ): Promise<{ url: string }> {\n debug(\n `open custom (${Object.entries(props)\n .map(([k, v]) => `${k}: ${v}`)\n .join(', ')})`\n );\n\n let url = this.props.getCustomRuntimeUrl({ scheme: props.scheme });\n debug(`Opening project in custom runtime: ${url} -- %O`, props);\n // TODO: It's unclear why we do application id validation when opening with a URL\n const applicationId = props.applicationId ?? (await this._getAppIdResolver().getAppIdAsync());\n\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n\n if (!(await deviceManager.isAppInstalledAsync(applicationId))) {\n throw new CommandError(\n `No development build (${applicationId}) for this project is installed. ` +\n `Please make and install a development build on the device first.\\n${learnMore(\n 'https://docs.expo.dev/development/build/'\n )}`\n );\n }\n\n // TODO: Rethink analytics\n await logEventAsync('Open Url on Device', {\n platform: this.props.platform,\n installedExpo: false,\n });\n\n if (!url) {\n url = this._resolveAlternativeLaunchUrl(applicationId, props);\n }\n\n deviceManager.logOpeningUrl(url);\n await deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n return {\n url,\n };\n }\n\n /** Launch the project on a device given the input runtime. */\n async openAsync(\n options:\n | {\n runtime: 'expo' | 'web';\n }\n | {\n runtime: 'custom';\n props?: Partial<IOpenInCustomProps>;\n },\n resolveSettings: Partial<IResolveDeviceProps> = {}\n ): Promise<{ url: string }> {\n debug(\n `open (runtime: ${options.runtime}, platform: ${this.props.platform}, device: %O, shouldPrompt: ${resolveSettings.shouldPrompt})`,\n resolveSettings.device\n );\n if (options.runtime === 'expo') {\n return this.openProjectInExpoGoAsync(resolveSettings);\n } else if (options.runtime === 'web') {\n return this.openWebProjectAsync(resolveSettings);\n } else if (options.runtime === 'custom') {\n return this.openProjectInCustomRuntimeAsync(resolveSettings, options.props);\n } else {\n throw new CommandError(`Invalid runtime target: ${options.runtime}`);\n }\n }\n\n /** Open the current web project (Webpack) in a device . */\n private async openWebProjectAsync(resolveSettings: Partial<IResolveDeviceProps> = {}): Promise<{\n url: string;\n }> {\n const url = this.props.getDevServerUrl();\n assert(url, 'Dev server is not running.');\n\n const deviceManager = await this.props.resolveDeviceAsync(resolveSettings);\n deviceManager.logOpeningUrl(url);\n await deviceManager.activateWindowAsync();\n await deviceManager.openUrlAsync(url);\n\n return { url };\n }\n\n /** If the launch URL cannot be determined (`custom` runtimes) then an alternative string can be provided to open the device. Often a device ID or activity to launch. Exposed for testing. */\n _resolveAlternativeLaunchUrl(\n applicationId: string,\n props: Partial<IOpenInCustomProps> = {}\n ): string {\n throw new UnimplementedError();\n }\n}\n"],"names":["debug","require","PlatformManager","constructor","projectRoot","props","_getAppIdResolver","UnimplementedError","getExpoGoOrCustomRuntimeUrlAsync","deviceManager","redirectUrl","getRedirectUrl","applicationId","getAppIdAsync","Log","warn","chalk","learnMore","isAppInstalledAsync","name","getExpoGoUrl","openProjectInExpoGoAsync","resolveSettings","resolveDeviceAsync","url","logOpeningUrl","exp","getConfig","installedExpo","ensureExpoGoAsync","sdkVersion","activateWindowAsync","openUrlAsync","logEventAsync","platform","openProjectInCustomRuntimeAsync","Object","entries","map","k","v","join","getCustomRuntimeUrl","scheme","CommandError","_resolveAlternativeLaunchUrl","openAsync","options","runtime","shouldPrompt","device","openWebProjectAsync","getDevServerUrl","assert"],"mappings":"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"}
|
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
exports.hasAdbReverseAsync = hasAdbReverseAsync;
|
|
5
6
|
exports.startAdbReverseAsync = startAdbReverseAsync;
|
|
6
7
|
exports.stopAdbReverseAsync = stopAdbReverseAsync;
|
|
7
8
|
var Log = _interopRequireWildcard(require("../../../log"));
|
|
8
9
|
var _exit = require("../../../utils/exit");
|
|
10
|
+
var _androidSdk = require("./AndroidSdk");
|
|
9
11
|
var _adb = require("./adb");
|
|
10
12
|
function _interopRequireWildcard(obj) {
|
|
11
13
|
if (obj && obj.__esModule) {
|
|
@@ -30,6 +32,14 @@ function _interopRequireWildcard(obj) {
|
|
|
30
32
|
}
|
|
31
33
|
const debug = require("debug")("expo:start:platforms:android:adbReverse");
|
|
32
34
|
let removeExitHook = null;
|
|
35
|
+
function hasAdbReverseAsync() {
|
|
36
|
+
try {
|
|
37
|
+
return !!(0, _androidSdk).assertSdkRoot();
|
|
38
|
+
} catch (error) {
|
|
39
|
+
debug("Failed to resolve the Android SDK path, skipping ADB: %s", error.message);
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
33
43
|
async function startAdbReverseAsync(ports) {
|
|
34
44
|
// Install cleanup automatically...
|
|
35
45
|
removeExitHook = (0, _exit).installExitHooks(()=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/platforms/android/adbReverse.ts"],"sourcesContent":["import * as Log from '../../../log';\nimport { installExitHooks } from '../../../utils/exit';\nimport { adbArgs, Device, getAttachedDevicesAsync, getServer, logUnauthorized } from './adb';\n\nconst debug = require('debug')('expo:start:platforms:android:adbReverse') as typeof console.log;\n\nlet removeExitHook: (() => void) | null = null;\n\nexport async function startAdbReverseAsync(ports: number[]): Promise<boolean> {\n // Install cleanup automatically...\n removeExitHook = installExitHooks(() => {\n stopAdbReverseAsync(ports);\n });\n\n const devices = await getAttachedDevicesAsync();\n for (const device of devices) {\n for (const port of ports) {\n if (!(await adbReverseAsync(device, port))) {\n debug(`Failed to start reverse port ${port} on device \"${device.name}\"`);\n return false;\n }\n }\n }\n return true;\n}\n\nexport async function stopAdbReverseAsync(ports: number[]): Promise<void> {\n removeExitHook?.();\n\n const devices = await getAttachedDevicesAsync();\n for (const device of devices) {\n for (const port of ports) {\n await adbReverseRemoveAsync(device, port);\n }\n }\n}\n\nasync function adbReverseAsync(device: Device, port: number): Promise<boolean> {\n if (!device.isAuthorized) {\n logUnauthorized(device);\n return false;\n }\n\n try {\n await getServer().runAsync(adbArgs(device.pid, 'reverse', `tcp:${port}`, `tcp:${port}`));\n return true;\n } catch (error: any) {\n Log.warn(`[ADB] Couldn't reverse port ${port}: ${error.message}`);\n return false;\n }\n}\n\nasync function adbReverseRemoveAsync(device: Device, port: number): Promise<boolean> {\n if (!device.isAuthorized) {\n return false;\n }\n\n try {\n await getServer().runAsync(adbArgs(device.pid, 'reverse', '--remove', `tcp:${port}`));\n return true;\n } catch (error: any) {\n // Don't send this to warn because we call this preemptively sometimes\n debug(`Could not unforward port ${port}: ${error.message}`);\n return false;\n }\n}\n"],"names":["startAdbReverseAsync","stopAdbReverseAsync","Log","debug","require","removeExitHook","ports","installExitHooks","devices","getAttachedDevicesAsync","device","port","adbReverseAsync","name","adbReverseRemoveAsync","isAuthorized","logUnauthorized","getServer","runAsync","adbArgs","pid","
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/platforms/android/adbReverse.ts"],"sourcesContent":["import * as Log from '../../../log';\nimport { installExitHooks } from '../../../utils/exit';\nimport { assertSdkRoot } from './AndroidSdk';\nimport { adbArgs, Device, getAttachedDevicesAsync, getServer, logUnauthorized } from './adb';\n\nconst debug = require('debug')('expo:start:platforms:android:adbReverse') as typeof console.log;\n\nlet removeExitHook: (() => void) | null = null;\n\nexport function hasAdbReverseAsync(): boolean {\n try {\n return !!assertSdkRoot();\n } catch (error: any) {\n debug('Failed to resolve the Android SDK path, skipping ADB: %s', error.message);\n return false;\n }\n}\n\nexport async function startAdbReverseAsync(ports: number[]): Promise<boolean> {\n // Install cleanup automatically...\n removeExitHook = installExitHooks(() => {\n stopAdbReverseAsync(ports);\n });\n\n const devices = await getAttachedDevicesAsync();\n for (const device of devices) {\n for (const port of ports) {\n if (!(await adbReverseAsync(device, port))) {\n debug(`Failed to start reverse port ${port} on device \"${device.name}\"`);\n return false;\n }\n }\n }\n return true;\n}\n\nexport async function stopAdbReverseAsync(ports: number[]): Promise<void> {\n removeExitHook?.();\n\n const devices = await getAttachedDevicesAsync();\n for (const device of devices) {\n for (const port of ports) {\n await adbReverseRemoveAsync(device, port);\n }\n }\n}\n\nasync function adbReverseAsync(device: Device, port: number): Promise<boolean> {\n if (!device.isAuthorized) {\n logUnauthorized(device);\n return false;\n }\n\n try {\n await getServer().runAsync(adbArgs(device.pid, 'reverse', `tcp:${port}`, `tcp:${port}`));\n return true;\n } catch (error: any) {\n Log.warn(`[ADB] Couldn't reverse port ${port}: ${error.message}`);\n return false;\n }\n}\n\nasync function adbReverseRemoveAsync(device: Device, port: number): Promise<boolean> {\n if (!device.isAuthorized) {\n return false;\n }\n\n try {\n await getServer().runAsync(adbArgs(device.pid, 'reverse', '--remove', `tcp:${port}`));\n return true;\n } catch (error: any) {\n // Don't send this to warn because we call this preemptively sometimes\n debug(`Could not unforward port ${port}: ${error.message}`);\n return false;\n }\n}\n"],"names":["hasAdbReverseAsync","startAdbReverseAsync","stopAdbReverseAsync","Log","debug","require","removeExitHook","assertSdkRoot","error","message","ports","installExitHooks","devices","getAttachedDevicesAsync","device","port","adbReverseAsync","name","adbReverseRemoveAsync","isAuthorized","logUnauthorized","getServer","runAsync","adbArgs","pid","warn"],"mappings":"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"}
|
|
@@ -54,7 +54,7 @@ async function resolveOptionsAsync(projectRoot, args) {
|
|
|
54
54
|
var ref;
|
|
55
55
|
return {
|
|
56
56
|
forceManifestType,
|
|
57
|
-
privateKeyPath: (ref = args["private-key-path"]) != null ? ref : null,
|
|
57
|
+
privateKeyPath: (ref = args["--private-key-path"]) != null ? ref : null,
|
|
58
58
|
android: !!args["--android"],
|
|
59
59
|
web: !!args["--web"],
|
|
60
60
|
ios: !!args["--ios"],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/start/resolveOptions.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { AbortCommandError, CommandError } from '../utils/errors';\nimport { resolvePortAsync } from '../utils/port';\n\nexport type Options = {\n forceManifestType: 'classic' | 'expo-updates';\n privateKeyPath: string | null;\n android: boolean;\n web: boolean;\n ios: boolean;\n offline: boolean;\n clear: boolean;\n dev: boolean;\n https: boolean;\n maxWorkers: number;\n port: number;\n /** Should instruct the bundler to create minified bundles. */\n minify: boolean;\n devClient: boolean;\n scheme: string | null;\n host: 'localhost' | 'lan' | 'tunnel';\n};\n\nexport async function resolveOptionsAsync(projectRoot: string, args: any): Promise<Options> {\n const forceManifestType = args['--force-manifest-type'];\n if (forceManifestType) {\n assert.match(forceManifestType, /^(classic|expo-updates)$/);\n }\n const host = resolveHostType({\n host: args['--host'],\n offline: args['--offline'],\n lan: args['--lan'],\n localhost: args['--localhost'],\n tunnel: args['--tunnel'],\n });\n\n const scheme = await resolveSchemeAsync(projectRoot, {\n scheme: args['--scheme'],\n devClient: args['--dev-client'],\n });\n\n return {\n forceManifestType,\n privateKeyPath: args['private-key-path'] ?? null,\n\n android: !!args['--android'],\n web: !!args['--web'],\n ios: !!args['--ios'],\n offline: !!args['--offline'],\n\n clear: !!args['--clear'],\n dev: !args['--no-dev'],\n https: !!args['--https'],\n maxWorkers: args['--max-workers'],\n port: args['--port'],\n minify: !!args['--minify'],\n\n devClient: !!args['--dev-client'],\n\n scheme,\n host,\n };\n}\n\nexport async function resolveSchemeAsync(\n projectRoot: string,\n options: { scheme?: string; devClient?: boolean }\n): Promise<string | null> {\n const resolveFrom = await import('resolve-from').then((m) => m.default);\n\n const isDevClientPackageInstalled = (() => {\n try {\n // we check if `expo-dev-launcher` is installed instead of `expo-dev-client`\n // because someone could install only launcher.\n resolveFrom(projectRoot, 'expo-dev-launcher');\n return true;\n } catch {\n return false;\n }\n })();\n\n if (typeof options.scheme === 'string') {\n // Use the custom scheme\n return options.scheme ?? null;\n } else if (options.devClient || isDevClientPackageInstalled) {\n const { getOptionalDevClientSchemeAsync } = await import('../utils/scheme');\n // Attempt to find the scheme or warn the user how to setup a custom scheme\n return await getOptionalDevClientSchemeAsync(projectRoot);\n } else {\n // Ensure this is reset when users don't use `--scheme`, `--dev-client` and don't have the `expo-dev-client` package installed.\n return null;\n }\n}\n\n/** Resolve and assert host type options. */\nexport function resolveHostType(options: {\n host?: string;\n offline?: boolean;\n lan?: boolean;\n localhost?: boolean;\n tunnel?: boolean;\n}): 'lan' | 'tunnel' | 'localhost' {\n if (\n [options.offline, options.host, options.lan, options.localhost, options.tunnel].filter((i) => i)\n .length > 1\n ) {\n throw new CommandError(\n 'BAD_ARGS',\n 'Specify at most one of: --offline, --host, --tunnel, --lan, --localhost'\n );\n }\n\n if (options.offline) {\n // Force `lan` in offline mode.\n return 'lan';\n } else if (options.host) {\n assert.match(options.host, /^(lan|tunnel|localhost)$/);\n return options.host as 'lan' | 'tunnel' | 'localhost';\n } else if (options.tunnel) {\n return 'tunnel';\n } else if (options.lan) {\n return 'lan';\n } else if (options.localhost) {\n return 'localhost';\n }\n return 'lan';\n}\n\n/** Resolve the port options for all supported bundlers. */\nexport async function resolvePortsAsync(\n projectRoot: string,\n options: Partial<Pick<Options, 'port' | 'devClient'>>,\n settings: { webOnly?: boolean }\n) {\n const multiBundlerSettings: { webpackPort?: number; metroPort?: number } = {};\n\n if (settings.webOnly) {\n const webpackPort = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n // Default web port\n fallbackPort: 19006,\n });\n if (!webpackPort) {\n throw new AbortCommandError();\n }\n multiBundlerSettings.webpackPort = webpackPort;\n } else {\n const devClientDefaultPort = process.env.RCT_METRO_PORT\n ? parseInt(process.env.RCT_METRO_PORT, 10)\n : 8081;\n const expoGoDefaultPort = 19000;\n const metroPort = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n fallbackPort: options.devClient ? devClientDefaultPort : expoGoDefaultPort,\n });\n if (!metroPort) {\n throw new AbortCommandError();\n }\n multiBundlerSettings.metroPort = metroPort;\n }\n\n return multiBundlerSettings;\n}\n"],"names":["resolveOptionsAsync","resolveSchemeAsync","resolveHostType","resolvePortsAsync","projectRoot","args","forceManifestType","assert","match","host","offline","lan","localhost","tunnel","scheme","devClient","privateKeyPath","android","web","ios","clear","dev","https","maxWorkers","port","minify","options","resolveFrom","then","m","default","isDevClientPackageInstalled","getOptionalDevClientSchemeAsync","filter","i","length","CommandError","settings","multiBundlerSettings","webOnly","webpackPort","resolvePortAsync","defaultPort","fallbackPort","AbortCommandError","devClientDefaultPort","process","env","RCT_METRO_PORT","parseInt","expoGoDefaultPort","metroPort"],"mappings":"AAAA;;;;QAwBsBA,mBAAmB,GAAnBA,mBAAmB;QAyCnBC,kBAAkB,GAAlBA,kBAAkB;QA+BxBC,eAAe,GAAfA,eAAe;QAkCTC,iBAAiB,GAAjBA,iBAAiB;AAlIpB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AAEqB,IAAA,OAAiB,WAAjB,iBAAiB,CAAA;AAChC,IAAA,KAAe,WAAf,eAAe,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBzC,eAAeH,mBAAmB,CAACI,WAAmB,EAAEC,IAAS,EAAoB;IAC1F,MAAMC,iBAAiB,GAAGD,IAAI,CAAC,uBAAuB,CAAC,AAAC;IACxD,IAAIC,iBAAiB,EAAE;QACrBC,OAAM,QAAA,CAACC,KAAK,CAACF,iBAAiB,6BAA6B,CAAC;KAC7D;IACD,MAAMG,IAAI,GAAGP,eAAe,CAAC;QAC3BO,IAAI,EAAEJ,IAAI,CAAC,QAAQ,CAAC;QACpBK,OAAO,EAAEL,IAAI,CAAC,WAAW,CAAC;QAC1BM,GAAG,EAAEN,IAAI,CAAC,OAAO,CAAC;QAClBO,SAAS,EAAEP,IAAI,CAAC,aAAa,CAAC;QAC9BQ,MAAM,EAAER,IAAI,CAAC,UAAU,CAAC;KACzB,CAAC,AAAC;IAEH,MAAMS,MAAM,GAAG,MAAMb,kBAAkB,CAACG,WAAW,EAAE;QACnDU,MAAM,EAAET,IAAI,CAAC,UAAU,CAAC;QACxBU,SAAS,EAAEV,IAAI,CAAC,cAAc,CAAC;KAChC,CAAC,AAAC;QAIeA,
|
|
1
|
+
{"version":3,"sources":["../../../src/start/resolveOptions.ts"],"sourcesContent":["import assert from 'assert';\n\nimport { AbortCommandError, CommandError } from '../utils/errors';\nimport { resolvePortAsync } from '../utils/port';\n\nexport type Options = {\n forceManifestType: 'classic' | 'expo-updates';\n privateKeyPath: string | null;\n android: boolean;\n web: boolean;\n ios: boolean;\n offline: boolean;\n clear: boolean;\n dev: boolean;\n https: boolean;\n maxWorkers: number;\n port: number;\n /** Should instruct the bundler to create minified bundles. */\n minify: boolean;\n devClient: boolean;\n scheme: string | null;\n host: 'localhost' | 'lan' | 'tunnel';\n};\n\nexport async function resolveOptionsAsync(projectRoot: string, args: any): Promise<Options> {\n const forceManifestType = args['--force-manifest-type'];\n if (forceManifestType) {\n assert.match(forceManifestType, /^(classic|expo-updates)$/);\n }\n const host = resolveHostType({\n host: args['--host'],\n offline: args['--offline'],\n lan: args['--lan'],\n localhost: args['--localhost'],\n tunnel: args['--tunnel'],\n });\n\n const scheme = await resolveSchemeAsync(projectRoot, {\n scheme: args['--scheme'],\n devClient: args['--dev-client'],\n });\n\n return {\n forceManifestType,\n privateKeyPath: args['--private-key-path'] ?? null,\n\n android: !!args['--android'],\n web: !!args['--web'],\n ios: !!args['--ios'],\n offline: !!args['--offline'],\n\n clear: !!args['--clear'],\n dev: !args['--no-dev'],\n https: !!args['--https'],\n maxWorkers: args['--max-workers'],\n port: args['--port'],\n minify: !!args['--minify'],\n\n devClient: !!args['--dev-client'],\n\n scheme,\n host,\n };\n}\n\nexport async function resolveSchemeAsync(\n projectRoot: string,\n options: { scheme?: string; devClient?: boolean }\n): Promise<string | null> {\n const resolveFrom = await import('resolve-from').then((m) => m.default);\n\n const isDevClientPackageInstalled = (() => {\n try {\n // we check if `expo-dev-launcher` is installed instead of `expo-dev-client`\n // because someone could install only launcher.\n resolveFrom(projectRoot, 'expo-dev-launcher');\n return true;\n } catch {\n return false;\n }\n })();\n\n if (typeof options.scheme === 'string') {\n // Use the custom scheme\n return options.scheme ?? null;\n } else if (options.devClient || isDevClientPackageInstalled) {\n const { getOptionalDevClientSchemeAsync } = await import('../utils/scheme');\n // Attempt to find the scheme or warn the user how to setup a custom scheme\n return await getOptionalDevClientSchemeAsync(projectRoot);\n } else {\n // Ensure this is reset when users don't use `--scheme`, `--dev-client` and don't have the `expo-dev-client` package installed.\n return null;\n }\n}\n\n/** Resolve and assert host type options. */\nexport function resolveHostType(options: {\n host?: string;\n offline?: boolean;\n lan?: boolean;\n localhost?: boolean;\n tunnel?: boolean;\n}): 'lan' | 'tunnel' | 'localhost' {\n if (\n [options.offline, options.host, options.lan, options.localhost, options.tunnel].filter((i) => i)\n .length > 1\n ) {\n throw new CommandError(\n 'BAD_ARGS',\n 'Specify at most one of: --offline, --host, --tunnel, --lan, --localhost'\n );\n }\n\n if (options.offline) {\n // Force `lan` in offline mode.\n return 'lan';\n } else if (options.host) {\n assert.match(options.host, /^(lan|tunnel|localhost)$/);\n return options.host as 'lan' | 'tunnel' | 'localhost';\n } else if (options.tunnel) {\n return 'tunnel';\n } else if (options.lan) {\n return 'lan';\n } else if (options.localhost) {\n return 'localhost';\n }\n return 'lan';\n}\n\n/** Resolve the port options for all supported bundlers. */\nexport async function resolvePortsAsync(\n projectRoot: string,\n options: Partial<Pick<Options, 'port' | 'devClient'>>,\n settings: { webOnly?: boolean }\n) {\n const multiBundlerSettings: { webpackPort?: number; metroPort?: number } = {};\n\n if (settings.webOnly) {\n const webpackPort = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n // Default web port\n fallbackPort: 19006,\n });\n if (!webpackPort) {\n throw new AbortCommandError();\n }\n multiBundlerSettings.webpackPort = webpackPort;\n } else {\n const devClientDefaultPort = process.env.RCT_METRO_PORT\n ? parseInt(process.env.RCT_METRO_PORT, 10)\n : 8081;\n const expoGoDefaultPort = 19000;\n const metroPort = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n fallbackPort: options.devClient ? devClientDefaultPort : expoGoDefaultPort,\n });\n if (!metroPort) {\n throw new AbortCommandError();\n }\n multiBundlerSettings.metroPort = metroPort;\n }\n\n return multiBundlerSettings;\n}\n"],"names":["resolveOptionsAsync","resolveSchemeAsync","resolveHostType","resolvePortsAsync","projectRoot","args","forceManifestType","assert","match","host","offline","lan","localhost","tunnel","scheme","devClient","privateKeyPath","android","web","ios","clear","dev","https","maxWorkers","port","minify","options","resolveFrom","then","m","default","isDevClientPackageInstalled","getOptionalDevClientSchemeAsync","filter","i","length","CommandError","settings","multiBundlerSettings","webOnly","webpackPort","resolvePortAsync","defaultPort","fallbackPort","AbortCommandError","devClientDefaultPort","process","env","RCT_METRO_PORT","parseInt","expoGoDefaultPort","metroPort"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ var _userSettings = _interopRequireDefault(require("../../api/user/UserSettings"
|
|
|
9
9
|
var _user = require("../../api/user/user");
|
|
10
10
|
var Log = _interopRequireWildcard(require("../../log"));
|
|
11
11
|
var _delay = require("../../utils/delay");
|
|
12
|
+
var _env = require("../../utils/env");
|
|
12
13
|
var _errors = require("../../utils/errors");
|
|
13
14
|
var _ngrokResolver = require("../doctor/ngrok/NgrokResolver");
|
|
14
15
|
var _adbReverse = require("../platforms/android/adbReverse");
|
|
@@ -55,7 +56,7 @@ class AsyncNgrok {
|
|
|
55
56
|
getActiveUrl() {
|
|
56
57
|
return this.serverUrl;
|
|
57
58
|
}
|
|
58
|
-
/** Exposed for testing. */ async
|
|
59
|
+
/** Exposed for testing. */ async _getIdentifyingUrlSegmentsAsync() {
|
|
59
60
|
const user = await (0, _user).getUserAsync();
|
|
60
61
|
if ((user == null ? void 0 : user.__typename) === "Robot") {
|
|
61
62
|
throw new _errors.CommandError("NGROK_ROBOT", "Cannot use ngrok with a robot user.");
|
|
@@ -66,22 +67,34 @@ class AsyncNgrok {
|
|
|
66
67
|
await this.getProjectRandomnessAsync(),
|
|
67
68
|
(0, _slugify).default(username),
|
|
68
69
|
// Use the port to distinguish between multiple tunnels (webpack, metro).
|
|
69
|
-
this.port,
|
|
70
|
-
|
|
70
|
+
String(this.port),
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
/** Exposed for testing. */ async _getProjectHostnameAsync() {
|
|
74
|
+
return [
|
|
75
|
+
...await this._getIdentifyingUrlSegmentsAsync(),
|
|
76
|
+
NGROK_CONFIG.domain
|
|
71
77
|
].join(".");
|
|
72
78
|
}
|
|
79
|
+
/** Exposed for testing. */ async _getProjectSubdomainAsync() {
|
|
80
|
+
return (await this._getIdentifyingUrlSegmentsAsync()).join("-");
|
|
81
|
+
}
|
|
73
82
|
/** Start ngrok on the given port for the project. */ async startAsync({ timeout } = {}) {
|
|
74
83
|
// Ensure the instance is loaded first, this can linger so we should run it before the timeout.
|
|
75
84
|
await this.resolver.resolveAsync({
|
|
76
85
|
// For now, prefer global install since the package has native code (harder to install) and doesn't change very often.
|
|
77
86
|
prefersGlobalInstall: true
|
|
78
87
|
});
|
|
79
|
-
//
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
// NOTE(EvanBacon): If the user doesn't have ADB installed,
|
|
89
|
+
// then skip attempting to reverse the port.
|
|
90
|
+
if ((0, _adbReverse).hasAdbReverseAsync()) {
|
|
91
|
+
// Ensure ADB reverse is running.
|
|
92
|
+
if (!await (0, _adbReverse).startAdbReverseAsync([
|
|
93
|
+
this.port
|
|
94
|
+
])) {
|
|
95
|
+
// TODO: Better error message.
|
|
96
|
+
throw new _errors.CommandError("NGROK_ADB", `Cannot start tunnel URL because \`adb reverse\` failed for the connected Android device(s).`);
|
|
97
|
+
}
|
|
85
98
|
}
|
|
86
99
|
this.serverUrl = await this._connectToNgrokAsync({
|
|
87
100
|
timeout
|
|
@@ -118,17 +131,32 @@ class AsyncNgrok {
|
|
|
118
131
|
await (0, _delay).delayAsync(100);
|
|
119
132
|
return this._connectToNgrokAsync(options, attempts + 1);
|
|
120
133
|
}
|
|
134
|
+
async _getConnectionPropsAsync() {
|
|
135
|
+
const userDefinedSubdomain = _env.env.EXPO_TUNNEL_SUBDOMAIN;
|
|
136
|
+
if (userDefinedSubdomain) {
|
|
137
|
+
const subdomain = typeof userDefinedSubdomain === "string" ? userDefinedSubdomain : await this._getProjectSubdomainAsync();
|
|
138
|
+
debug("Subdomain:", subdomain);
|
|
139
|
+
return {
|
|
140
|
+
subdomain
|
|
141
|
+
};
|
|
142
|
+
} else {
|
|
143
|
+
const hostname = await this._getProjectHostnameAsync();
|
|
144
|
+
debug("Hostname:", hostname);
|
|
145
|
+
return {
|
|
146
|
+
hostname
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
121
150
|
async connectToNgrokInternalAsync(instance, attempts = 0) {
|
|
122
151
|
try {
|
|
123
152
|
// Global config path.
|
|
124
153
|
const configPath = path.join(_userSettings.default.getDirectory(), "ngrok.yml");
|
|
125
154
|
debug("Global config path:", configPath);
|
|
126
|
-
const
|
|
127
|
-
debug("Hostname:", hostname);
|
|
155
|
+
const urlProps = await this._getConnectionPropsAsync();
|
|
128
156
|
const url = await instance.connect({
|
|
157
|
+
...urlProps,
|
|
129
158
|
authtoken: NGROK_CONFIG.authToken,
|
|
130
159
|
proto: "http",
|
|
131
|
-
hostname,
|
|
132
160
|
configPath,
|
|
133
161
|
onStatusChange (status) {
|
|
134
162
|
if (status === "closed") {
|
|
@@ -141,12 +169,28 @@ class AsyncNgrok {
|
|
|
141
169
|
});
|
|
142
170
|
return url;
|
|
143
171
|
} catch (error) {
|
|
172
|
+
const assertNgrok = ()=>{
|
|
173
|
+
if ((0, _ngrokResolver).isNgrokClientError(error)) {
|
|
174
|
+
var ref;
|
|
175
|
+
throw new _errors.CommandError("NGROK_CONNECT", [
|
|
176
|
+
error.body.msg,
|
|
177
|
+
(ref = error.body.details) == null ? void 0 : ref.err
|
|
178
|
+
].filter(Boolean).join("\n\n"));
|
|
179
|
+
}
|
|
180
|
+
throw new _errors.CommandError("NGROK_CONNECT", error.toString());
|
|
181
|
+
};
|
|
144
182
|
// Attempt to connect 3 times
|
|
145
183
|
if (attempts >= 2) {
|
|
146
|
-
|
|
184
|
+
assertNgrok();
|
|
147
185
|
}
|
|
148
186
|
// Attempt to fix the issue
|
|
149
|
-
if ((error
|
|
187
|
+
if ((0, _ngrokResolver).isNgrokClientError(error) && error.body.error_code === 103) {
|
|
188
|
+
// Assert early if a custom subdomain is used since it cannot
|
|
189
|
+
// be changed and retried. If the tunnel subdomain is a boolean
|
|
190
|
+
// then we can reset the randomness and try again.
|
|
191
|
+
if (typeof _env.env.EXPO_TUNNEL_SUBDOMAIN === "string") {
|
|
192
|
+
assertNgrok();
|
|
193
|
+
}
|
|
150
194
|
// Change randomness to avoid conflict if killing ngrok doesn't help
|
|
151
195
|
await this._resetProjectRandomnessAsync();
|
|
152
196
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/start/server/AsyncNgrok.ts"],"sourcesContent":["import crypto from 'crypto';\nimport * as path from 'path';\nimport slugify from 'slugify';\n\nimport UserSettings from '../../api/user/UserSettings';\nimport { getActorDisplayName, getUserAsync } from '../../api/user/user';\nimport * as Log from '../../log';\nimport { delayAsync, resolveWithTimeout } from '../../utils/delay';\nimport { CommandError } from '../../utils/errors';\nimport { NgrokInstance, NgrokResolver } from '../doctor/ngrok/NgrokResolver';\nimport { startAdbReverseAsync } from '../platforms/android/adbReverse';\nimport { ProjectSettings } from '../project/settings';\n\nconst debug = require('debug')('expo:start:server:ngrok') as typeof console.log;\n\nconst NGROK_CONFIG = {\n authToken: '5W1bR67GNbWcXqmxZzBG1_56GezNeaX6sSRvn8npeQ8',\n domain: 'exp.direct',\n};\n\nconst TUNNEL_TIMEOUT = 10 * 1000;\n\nexport class AsyncNgrok {\n /** Resolves the best instance of ngrok, exposed for testing. */\n resolver: NgrokResolver;\n\n /** Info about the currently running instance of ngrok. */\n private serverUrl: string | null = null;\n\n constructor(private projectRoot: string, private port: number) {\n this.resolver = new NgrokResolver(projectRoot);\n }\n\n public getActiveUrl(): string | null {\n return this.serverUrl;\n }\n\n /** Exposed for testing. */\n async _getProjectHostnameAsync() {\n const user = await getUserAsync();\n if (user?.__typename === 'Robot') {\n throw new CommandError('NGROK_ROBOT', 'Cannot use ngrok with a robot user.');\n }\n const username = getActorDisplayName(user);\n\n return [\n // NOTE: https://github.com/expo/expo/pull/16556#discussion_r822944286\n await this.getProjectRandomnessAsync(),\n slugify(username),\n // Use the port to distinguish between multiple tunnels (webpack, metro).\n this.port,\n NGROK_CONFIG.domain,\n ].join('.');\n }\n\n /** Start ngrok on the given port for the project. */\n async startAsync({ timeout }: { timeout?: number } = {}): Promise<void> {\n // Ensure the instance is loaded first, this can linger so we should run it before the timeout.\n await this.resolver.resolveAsync({\n // For now, prefer global install since the package has native code (harder to install) and doesn't change very often.\n prefersGlobalInstall: true,\n });\n\n // Ensure ADB reverse is running.\n if (!(await startAdbReverseAsync([this.port]))) {\n // TODO: Better error message.\n throw new CommandError(\n 'NGROK_ADB',\n `Cannot start tunnel URL because \\`adb reverse\\` failed for the connected Android device(s).`\n );\n }\n\n this.serverUrl = await this._connectToNgrokAsync({ timeout });\n\n debug('Tunnel URL:', this.serverUrl);\n Log.log('Tunnel ready.');\n }\n\n /** Stop the ngrok process if it's running. */\n public async stopAsync(): Promise<void> {\n debug('Stopping Tunnel');\n\n await this.resolver.get()?.kill?.();\n this.serverUrl = null;\n }\n\n /** Exposed for testing. */\n async _connectToNgrokAsync(\n options: { timeout?: number } = {},\n attempts: number = 0\n ): Promise<string> {\n // Attempt to stop any hanging processes, this increases the chances of a successful connection.\n await this.stopAsync();\n\n // Get the instance quietly or assert otherwise.\n const instance = await this.resolver.resolveAsync({\n shouldPrompt: false,\n autoInstall: false,\n });\n\n // TODO(Bacon): Consider dropping the timeout functionality:\n // https://github.com/expo/expo/pull/16556#discussion_r822307373\n const results = await resolveWithTimeout(\n () => this.connectToNgrokInternalAsync(instance, attempts),\n {\n timeout: options.timeout ?? TUNNEL_TIMEOUT,\n errorMessage: 'ngrok tunnel took too long to connect.',\n }\n );\n if (typeof results === 'string') {\n return results;\n }\n\n // Wait 100ms and then try again\n await delayAsync(100);\n\n return this._connectToNgrokAsync(options, attempts + 1);\n }\n\n private async connectToNgrokInternalAsync(\n instance: NgrokInstance,\n attempts: number = 0\n ): Promise<string | false> {\n try {\n // Global config path.\n const configPath = path.join(UserSettings.getDirectory(), 'ngrok.yml');\n debug('Global config path:', configPath);\n const hostname = await this._getProjectHostnameAsync();\n debug('Hostname:', hostname);\n\n const url = await instance.connect({\n authtoken: NGROK_CONFIG.authToken,\n proto: 'http',\n hostname,\n configPath,\n onStatusChange(status) {\n if (status === 'closed') {\n Log.error(\n 'We noticed your tunnel is having issues. ' +\n 'This may be due to intermittent problems with ngrok. ' +\n 'If you have trouble connecting to your app, try to restart the project, ' +\n 'or switch the host to `lan`.'\n );\n } else if (status === 'connected') {\n Log.log('Tunnel connected.');\n }\n },\n port: this.port,\n });\n return url;\n } catch (error: any) {\n // Attempt to connect 3 times\n if (attempts >= 2) {\n throw new CommandError('NGROK_CONNECT', error.toString());\n }\n\n // Attempt to fix the issue\n if (error?.error_code === 103) {\n // Change randomness to avoid conflict if killing ngrok doesn't help\n await this._resetProjectRandomnessAsync();\n }\n return false;\n }\n }\n\n private async getProjectRandomnessAsync() {\n const { urlRandomness: randomness } = await ProjectSettings.readAsync(this.projectRoot);\n if (randomness) {\n return randomness;\n }\n return await this._resetProjectRandomnessAsync();\n }\n\n async _resetProjectRandomnessAsync() {\n const randomness = crypto.randomBytes(5).toString('base64url');\n await ProjectSettings.setAsync(this.projectRoot, { urlRandomness: randomness });\n debug('Resetting project randomness:', randomness);\n return randomness;\n }\n}\n"],"names":["path","Log","debug","require","NGROK_CONFIG","authToken","domain","TUNNEL_TIMEOUT","AsyncNgrok","constructor","projectRoot","port","serverUrl","resolver","NgrokResolver","getActiveUrl","_getProjectHostnameAsync","user","getUserAsync","__typename","CommandError","username","getActorDisplayName","getProjectRandomnessAsync","slugify","join","startAsync","timeout","resolveAsync","prefersGlobalInstall","startAdbReverseAsync","_connectToNgrokAsync","log","stopAsync","get","kill","options","attempts","instance","shouldPrompt","autoInstall","results","resolveWithTimeout","connectToNgrokInternalAsync","errorMessage","delayAsync","configPath","UserSettings","getDirectory","hostname","url","connect","authtoken","proto","onStatusChange","status","error","toString","error_code","_resetProjectRandomnessAsync","urlRandomness","randomness","ProjectSettings","readAsync","crypto","randomBytes","setAsync"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/start/server/AsyncNgrok.ts"],"sourcesContent":["import crypto from 'crypto';\nimport * as path from 'path';\nimport slugify from 'slugify';\n\nimport UserSettings from '../../api/user/UserSettings';\nimport { getActorDisplayName, getUserAsync } from '../../api/user/user';\nimport * as Log from '../../log';\nimport { delayAsync, resolveWithTimeout } from '../../utils/delay';\nimport { env } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport { isNgrokClientError, NgrokInstance, NgrokResolver } from '../doctor/ngrok/NgrokResolver';\nimport { hasAdbReverseAsync, startAdbReverseAsync } from '../platforms/android/adbReverse';\nimport { ProjectSettings } from '../project/settings';\n\nconst debug = require('debug')('expo:start:server:ngrok') as typeof console.log;\n\nconst NGROK_CONFIG = {\n authToken: '5W1bR67GNbWcXqmxZzBG1_56GezNeaX6sSRvn8npeQ8',\n domain: 'exp.direct',\n};\n\nconst TUNNEL_TIMEOUT = 10 * 1000;\n\nexport class AsyncNgrok {\n /** Resolves the best instance of ngrok, exposed for testing. */\n resolver: NgrokResolver;\n\n /** Info about the currently running instance of ngrok. */\n private serverUrl: string | null = null;\n\n constructor(private projectRoot: string, private port: number) {\n this.resolver = new NgrokResolver(projectRoot);\n }\n\n public getActiveUrl(): string | null {\n return this.serverUrl;\n }\n\n /** Exposed for testing. */\n async _getIdentifyingUrlSegmentsAsync(): Promise<string[]> {\n const user = await getUserAsync();\n if (user?.__typename === 'Robot') {\n throw new CommandError('NGROK_ROBOT', 'Cannot use ngrok with a robot user.');\n }\n const username = getActorDisplayName(user);\n\n return [\n // NOTE: https://github.com/expo/expo/pull/16556#discussion_r822944286\n await this.getProjectRandomnessAsync(),\n slugify(username),\n // Use the port to distinguish between multiple tunnels (webpack, metro).\n String(this.port),\n ];\n }\n\n /** Exposed for testing. */\n async _getProjectHostnameAsync(): Promise<string> {\n return [...(await this._getIdentifyingUrlSegmentsAsync()), NGROK_CONFIG.domain].join('.');\n }\n\n /** Exposed for testing. */\n async _getProjectSubdomainAsync(): Promise<string> {\n return (await this._getIdentifyingUrlSegmentsAsync()).join('-');\n }\n\n /** Start ngrok on the given port for the project. */\n async startAsync({ timeout }: { timeout?: number } = {}): Promise<void> {\n // Ensure the instance is loaded first, this can linger so we should run it before the timeout.\n await this.resolver.resolveAsync({\n // For now, prefer global install since the package has native code (harder to install) and doesn't change very often.\n prefersGlobalInstall: true,\n });\n\n // NOTE(EvanBacon): If the user doesn't have ADB installed,\n // then skip attempting to reverse the port.\n if (hasAdbReverseAsync()) {\n // Ensure ADB reverse is running.\n if (!(await startAdbReverseAsync([this.port]))) {\n // TODO: Better error message.\n throw new CommandError(\n 'NGROK_ADB',\n `Cannot start tunnel URL because \\`adb reverse\\` failed for the connected Android device(s).`\n );\n }\n }\n\n this.serverUrl = await this._connectToNgrokAsync({ timeout });\n\n debug('Tunnel URL:', this.serverUrl);\n Log.log('Tunnel ready.');\n }\n\n /** Stop the ngrok process if it's running. */\n public async stopAsync(): Promise<void> {\n debug('Stopping Tunnel');\n\n await this.resolver.get()?.kill?.();\n this.serverUrl = null;\n }\n\n /** Exposed for testing. */\n async _connectToNgrokAsync(\n options: { timeout?: number } = {},\n attempts: number = 0\n ): Promise<string> {\n // Attempt to stop any hanging processes, this increases the chances of a successful connection.\n await this.stopAsync();\n\n // Get the instance quietly or assert otherwise.\n const instance = await this.resolver.resolveAsync({\n shouldPrompt: false,\n autoInstall: false,\n });\n\n // TODO(Bacon): Consider dropping the timeout functionality:\n // https://github.com/expo/expo/pull/16556#discussion_r822307373\n const results = await resolveWithTimeout(\n () => this.connectToNgrokInternalAsync(instance, attempts),\n {\n timeout: options.timeout ?? TUNNEL_TIMEOUT,\n errorMessage: 'ngrok tunnel took too long to connect.',\n }\n );\n if (typeof results === 'string') {\n return results;\n }\n\n // Wait 100ms and then try again\n await delayAsync(100);\n\n return this._connectToNgrokAsync(options, attempts + 1);\n }\n\n private async _getConnectionPropsAsync(): Promise<{ hostname?: string; subdomain?: string }> {\n const userDefinedSubdomain = env.EXPO_TUNNEL_SUBDOMAIN;\n if (userDefinedSubdomain) {\n const subdomain =\n typeof userDefinedSubdomain === 'string'\n ? userDefinedSubdomain\n : await this._getProjectSubdomainAsync();\n debug('Subdomain:', subdomain);\n return { subdomain };\n } else {\n const hostname = await this._getProjectHostnameAsync();\n debug('Hostname:', hostname);\n return { hostname };\n }\n }\n\n private async connectToNgrokInternalAsync(\n instance: NgrokInstance,\n attempts: number = 0\n ): Promise<string | false> {\n try {\n // Global config path.\n const configPath = path.join(UserSettings.getDirectory(), 'ngrok.yml');\n debug('Global config path:', configPath);\n const urlProps = await this._getConnectionPropsAsync();\n\n const url = await instance.connect({\n ...urlProps,\n authtoken: NGROK_CONFIG.authToken,\n proto: 'http',\n configPath,\n onStatusChange(status) {\n if (status === 'closed') {\n Log.error(\n 'We noticed your tunnel is having issues. ' +\n 'This may be due to intermittent problems with ngrok. ' +\n 'If you have trouble connecting to your app, try to restart the project, ' +\n 'or switch the host to `lan`.'\n );\n } else if (status === 'connected') {\n Log.log('Tunnel connected.');\n }\n },\n port: this.port,\n });\n return url;\n } catch (error: any) {\n const assertNgrok = () => {\n if (isNgrokClientError(error)) {\n throw new CommandError(\n 'NGROK_CONNECT',\n [error.body.msg, error.body.details?.err].filter(Boolean).join('\\n\\n')\n );\n }\n throw new CommandError('NGROK_CONNECT', error.toString());\n };\n\n // Attempt to connect 3 times\n if (attempts >= 2) {\n assertNgrok();\n }\n\n // Attempt to fix the issue\n if (isNgrokClientError(error) && error.body.error_code === 103) {\n // Assert early if a custom subdomain is used since it cannot\n // be changed and retried. If the tunnel subdomain is a boolean\n // then we can reset the randomness and try again.\n if (typeof env.EXPO_TUNNEL_SUBDOMAIN === 'string') {\n assertNgrok();\n }\n // Change randomness to avoid conflict if killing ngrok doesn't help\n await this._resetProjectRandomnessAsync();\n }\n\n return false;\n }\n }\n\n private async getProjectRandomnessAsync() {\n const { urlRandomness: randomness } = await ProjectSettings.readAsync(this.projectRoot);\n if (randomness) {\n return randomness;\n }\n return await this._resetProjectRandomnessAsync();\n }\n\n async _resetProjectRandomnessAsync() {\n const randomness = crypto.randomBytes(5).toString('base64url');\n await ProjectSettings.setAsync(this.projectRoot, { urlRandomness: randomness });\n debug('Resetting project randomness:', randomness);\n return randomness;\n }\n}\n"],"names":["path","Log","debug","require","NGROK_CONFIG","authToken","domain","TUNNEL_TIMEOUT","AsyncNgrok","constructor","projectRoot","port","serverUrl","resolver","NgrokResolver","getActiveUrl","_getIdentifyingUrlSegmentsAsync","user","getUserAsync","__typename","CommandError","username","getActorDisplayName","getProjectRandomnessAsync","slugify","String","_getProjectHostnameAsync","join","_getProjectSubdomainAsync","startAsync","timeout","resolveAsync","prefersGlobalInstall","hasAdbReverseAsync","startAdbReverseAsync","_connectToNgrokAsync","log","stopAsync","get","kill","options","attempts","instance","shouldPrompt","autoInstall","results","resolveWithTimeout","connectToNgrokInternalAsync","errorMessage","delayAsync","_getConnectionPropsAsync","userDefinedSubdomain","env","EXPO_TUNNEL_SUBDOMAIN","subdomain","hostname","configPath","UserSettings","getDirectory","urlProps","url","connect","authtoken","proto","onStatusChange","status","error","assertNgrok","isNgrokClientError","body","msg","details","err","filter","Boolean","toString","error_code","_resetProjectRandomnessAsync","urlRandomness","randomness","ProjectSettings","readAsync","crypto","randomBytes","setAsync"],"mappings":"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"}
|
|
@@ -154,7 +154,20 @@ class BundlerDevServer {
|
|
|
154
154
|
this.devSession = new _developmentSession.DevelopmentSession(this.projectRoot, // This URL will be used on external devices so the computer IP won't be relevant.
|
|
155
155
|
this.isTargetingNative() ? this.getNativeRuntimeUrl() : this.getDevServerUrl({
|
|
156
156
|
hostType: "localhost"
|
|
157
|
-
}))
|
|
157
|
+
}), ()=>{
|
|
158
|
+
var // TODO: This appears to be happening consistently after an hour.
|
|
159
|
+
// We should investigate why this is happening and fix it on our servers.
|
|
160
|
+
// Log.error(
|
|
161
|
+
// chalk.red(
|
|
162
|
+
// '\nAn unexpected error occurred while updating the Dev Session API. This project will not appear in the "Development servers" section of the Expo Go app until this process has been restarted.'
|
|
163
|
+
// )
|
|
164
|
+
// );
|
|
165
|
+
// Log.exception(error);
|
|
166
|
+
ref;
|
|
167
|
+
(ref = this.devSession) == null ? void 0 : ref.closeAsync().catch((error)=>{
|
|
168
|
+
debug("[dev-session] error closing: " + error.message);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
158
171
|
await this.devSession.startAsync({
|
|
159
172
|
runtime: this.isTargetingNative() ? "native" : "web"
|
|
160
173
|
});
|
|
@@ -251,9 +264,12 @@ class BundlerDevServer {
|
|
|
251
264
|
}
|
|
252
265
|
/** Open the dev server in a runtime. */ async openPlatformAsync(launchTarget, resolver = {}) {
|
|
253
266
|
if (launchTarget === "desktop") {
|
|
254
|
-
const
|
|
267
|
+
const serverUrl = this.getDevServerUrl({
|
|
255
268
|
hostType: "localhost"
|
|
256
269
|
});
|
|
270
|
+
var ref;
|
|
271
|
+
// Allow opening the tunnel URL when using Metro web.
|
|
272
|
+
const url = this.name === "metro" ? (ref = this.getTunnelUrl()) != null ? ref : serverUrl : serverUrl;
|
|
257
273
|
await (0, _betterOpn).default(url);
|
|
258
274
|
return {
|
|
259
275
|
url
|