@expo/cli 0.3.2 → 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/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/ngrok/NgrokResolver.js +5 -0
- package/build/src/start/doctor/ngrok/NgrokResolver.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 +4 -1
- package/build/src/start/server/BundlerDevServer.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
|
@@ -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":"AAAA;;;;AAA0B,IAAA,OAAc,WAAd,cAAc,CAAA;AACrB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AACT,IAAA,MAAO,kCAAP,OAAO,EAAA;AAEL,IAAA,IAAW,WAAX,WAAW,CAAA;AACD,IAAA,kBAAyC,WAAzC,yCAAyC,CAAA;AACtB,IAAA,OAAoB,WAApB,oBAAoB,CAAA;AAC3C,IAAA,KAAkB,WAAlB,kBAAkB,CAAA;;;;;;AAI5C,MAAMA,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,sCAAsC,CAAC,AAAsB,AAAC;AAetF,MAAMC,eAAe;IAK1BC,YACYC,WAAmB,EACnBC,KAiBT,CACD;aAnBUD,WAAmB,GAAnBA,WAAmB;aACnBC,KAiBT,GAjBSA,KAiBT;KACC;IAEJ,0GAA0G,CAC1GC,iBAAiB,GAAkB;QACjC,MAAM,IAAIC,OAAkB,mBAAA,EAAE,CAAC;KAChC;IAED;;;;KAIG,CACH,MAAgBC,gCAAgC,CAC9CC,aAAqC,EACpB;QACjB,4FAA4F;QAC5F,MAAMC,WAAW,GAAG,IAAI,CAACL,KAAK,CAACM,cAAc,EAAE,AAAC;QAChD,IAAID,WAAW,EAAE;YACf,oGAAoG;YACpG,IAAIE,aAAa,AAAC;YAClB,IAAI;gBACFA,aAAa,GAAG,MAAM,IAAI,CAACN,iBAAiB,EAAE,CAACO,aAAa,EAAE,CAAC;aAChE,CAAC,OAAM;gBACNC,IAAG,IAAA,CAACC,IAAI,CACNC,MAAK,QAAA,CAAC,kDAAkD,CAAC,GACvD,CAAC,gFAAgF,CAAC,GAClFA,MAAK,QAAA,CAAC,4EAA4E,CAAC,GACnF,CAAC,4BAA4B,EAAEC,CAAAA,GAAAA,KAAS,AAA4C,CAAA,UAA5C,CAAC,0CAA0C,CAAC,CAAC,CAAC,CACzF,CAAC;aACH;YACD,IAAIL,aAAa,EAAE;gBACjBZ,KAAK,CAAC,CAAC,8BAA8B,EAAEY,aAAa,CAAC,gBAAgB,EAAEF,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;gBACvF,sHAAsH;gBACtH,4EAA4E;gBAC5E,IAAI,MAAMD,aAAa,CAACS,mBAAmB,CAACN,aAAa,CAAC,EAAE;oBAC1D,OAAOF,WAAW,CAAC;iBACpB,MAAM;oBACL,4EAA4E;oBAC5E,+CAA+C;oBAC/CI,IAAG,IAAA,CAACC,IAAI,CACNC,MAAK,QAAA,CAAC,uFAAuF,CAAC,GAC5FA,MAAK,QAAA,CAAC,mBAAmB,EAAEP,aAAa,CAACU,IAAI,CAAC,+CAA+C,CAAC,GAC9F,CAAC,8DAA8D,EAAEF,CAAAA,GAAAA,KAAS,AAEzE,CAAA,UAFyE,CACxE,0CAA0C,CAC3C,CAAC,CAAC,CACN,CAAC;iBACH;aACF;SACF;QAED,OAAO,IAAI,CAACZ,KAAK,CAACe,YAAY,EAAE,CAAC;KAClC;IAED,MAAgBC,wBAAwB,CACtCC,eAA6C,GAAG,EAAE,EACxB;QAC1B,MAAMb,aAAa,GAAG,MAAM,IAAI,CAACJ,KAAK,CAACkB,kBAAkB,CAACD,eAAe,CAAC,AAAC;QAC3E,MAAME,GAAG,GAAG,MAAM,IAAI,CAAChB,gCAAgC,CAACC,aAAa,CAAC,AAAC;QAEvEA,aAAa,CAACgB,aAAa,CAACD,GAAG,CAAC,CAAC;QAEjC,gDAAgD;QAChD,MAAM,EAAEE,GAAG,CAAA,EAAE,GAAGC,CAAAA,GAAAA,OAAS,AAAkB,CAAA,UAAlB,CAAC,IAAI,CAACvB,WAAW,CAAC,AAAC;QAC5C,MAAMwB,aAAa,GAAG,MAAMnB,aAAa,CAACoB,iBAAiB,CAACH,GAAG,CAACI,UAAU,CAAC,AAAC;QAE5ErB,aAAa,CAACsB,mBAAmB,EAAE,CAAC;QACpC,MAAMtB,aAAa,CAACuB,YAAY,CAACR,GAAG,CAAC,CAAC;QAEtC,MAAMS,CAAAA,GAAAA,kBAAa,AAGjB,CAAA,cAHiB,CAAC,oBAAoB,EAAE;YACxCC,QAAQ,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,QAAQ;YAC7BN,aAAa;SACd,CAAC,CAAC;QAEH,OAAO;YAAEJ,GAAG;SAAE,CAAC;KAChB;IAED,MAAcW,+BAA+B,CAC3Cb,eAA6C,GAAG,EAAE,EAClDjB,KAAkC,GAAG,EAAE,EACb;QAC1BL,KAAK,CACH,CAAC,aAAa,EAAEoC,MAAM,CAACC,OAAO,CAAChC,KAAK,CAAC,CAClCiC,GAAG,CAAC,CAAC,CAACC,CAAC,EAAEC,CAAC,CAAC,GAAK,CAAC,EAAED,CAAC,CAAC,EAAE,EAAEC,CAAC,CAAC,CAAC;QAAA,CAAC,CAC7BC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CACjB,CAAC;QAEF,IAAIjB,GAAG,GAAG,IAAI,CAACnB,KAAK,CAACqC,mBAAmB,CAAC;YAAEC,MAAM,EAAEtC,KAAK,CAACsC,MAAM;SAAE,CAAC,AAAC;QACnE3C,KAAK,CAAC,CAAC,mCAAmC,EAAEwB,GAAG,CAAC,MAAM,CAAC,EAAEnB,KAAK,CAAC,CAAC;YAE1CA,cAAmB;QADzC,iFAAiF;QACjF,MAAMO,aAAa,GAAGP,CAAAA,cAAmB,GAAnBA,KAAK,CAACO,aAAa,YAAnBP,cAAmB,GAAK,MAAM,IAAI,CAACC,iBAAiB,EAAE,CAACO,aAAa,EAAE,AAAC,AAAC;QAE9F,MAAMJ,aAAa,GAAG,MAAM,IAAI,CAACJ,KAAK,CAACkB,kBAAkB,CAACD,eAAe,CAAC,AAAC;QAE3E,IAAI,CAAE,MAAMb,aAAa,CAACS,mBAAmB,CAACN,aAAa,CAAC,AAAC,EAAE;YAC7D,MAAM,IAAIgC,OAAY,aAAA,CACpB,CAAC,sBAAsB,EAAEhC,aAAa,CAAC,iCAAiC,CAAC,GACvE,CAAC,kEAAkE,EAAEK,CAAAA,GAAAA,KAAS,AAE7E,CAAA,UAF6E,CAC5E,0CAA0C,CAC3C,CAAC,CAAC,CACN,CAAC;SACH;QAED,0BAA0B;QAC1B,MAAMgB,CAAAA,GAAAA,kBAAa,AAGjB,CAAA,cAHiB,CAAC,oBAAoB,EAAE;YACxCC,QAAQ,EAAE,IAAI,CAAC7B,KAAK,CAAC6B,QAAQ;YAC7BN,aAAa,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,IAAI,CAACJ,GAAG,EAAE;YACRA,GAAG,GAAG,IAAI,CAACqB,4BAA4B,CAACjC,aAAa,EAAEP,KAAK,CAAC,CAAC;SAC/D;QAEDI,aAAa,CAACgB,aAAa,CAACD,GAAG,CAAC,CAAC;QACjC,MAAMf,aAAa,CAACsB,mBAAmB,EAAE,CAAC;QAC1C,MAAMtB,aAAa,CAACuB,YAAY,CAACR,GAAG,CAAC,CAAC;QAEtC,OAAO;YACLA,GAAG;SACJ,CAAC;KACH;IAED,8DAA8D,CAC9D,MAAMsB,SAAS,CACbC,OAOK,EACLzB,eAA6C,GAAG,EAAE,EACxB;QAC1BtB,KAAK,CACH,CAAC,eAAe,EAAE+C,OAAO,CAACC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC3C,KAAK,CAAC6B,QAAQ,CAAC,4BAA4B,EAAEZ,eAAe,CAAC2B,YAAY,CAAC,CAAC,CAAC,EACjI3B,eAAe,CAAC4B,MAAM,CACvB,CAAC;QACF,IAAIH,OAAO,CAACC,OAAO,KAAK,MAAM,EAAE;YAC9B,OAAO,IAAI,CAAC3B,wBAAwB,CAACC,eAAe,CAAC,CAAC;SACvD,MAAM,IAAIyB,OAAO,CAACC,OAAO,KAAK,KAAK,EAAE;YACpC,OAAO,IAAI,CAACG,mBAAmB,CAAC7B,eAAe,CAAC,CAAC;SAClD,MAAM,IAAIyB,OAAO,CAACC,OAAO,KAAK,QAAQ,EAAE;YACvC,OAAO,IAAI,CAACb,+BAA+B,CAACb,eAAe,EAAEyB,OAAO,CAAC1C,KAAK,CAAC,CAAC;SAC7E,MAAM;YACL,MAAM,IAAIuC,OAAY,aAAA,CAAC,CAAC,wBAAwB,EAAEG,OAAO,CAACC,OAAO,CAAC,CAAC,CAAC,CAAC;SACtE;KACF;IAED,2DAA2D,CAC3D,MAAcG,mBAAmB,CAAC7B,eAA6C,GAAG,EAAE,EAEjF;QACD,MAAME,GAAG,GAAG,IAAI,CAACnB,KAAK,CAAC+C,eAAe,EAAE,AAAC;QACzCC,CAAAA,GAAAA,OAAM,AAAmC,CAAA,QAAnC,CAAC7B,GAAG,EAAE,4BAA4B,CAAC,CAAC;QAE1C,MAAMf,aAAa,GAAG,MAAM,IAAI,CAACJ,KAAK,CAACkB,kBAAkB,CAACD,eAAe,CAAC,AAAC;QAC3Eb,aAAa,CAACgB,aAAa,CAACD,GAAG,CAAC,CAAC;QACjC,MAAMf,aAAa,CAACsB,mBAAmB,EAAE,CAAC;QAC1C,MAAMtB,aAAa,CAACuB,YAAY,CAACR,GAAG,CAAC,CAAC;QAEtC,OAAO;YAAEA,GAAG;SAAE,CAAC;KAChB;IAED,8LAA8L,CAC9LqB,4BAA4B,CAC1BjC,aAAqB,EACrBP,KAAkC,GAAG,EAAE,EAC/B;QACR,MAAM,IAAIE,OAAkB,mBAAA,EAAE,CAAC;KAChC;CACF;QAnMYL,eAAe,GAAfA,eAAe"}
|
|
@@ -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":"AAAA;;;;AAAmB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AACfA,IAAAA,IAAI,mCAAM,MAAM,EAAZ;AACI,IAAA,QAAS,kCAAT,SAAS,EAAA;AAEJ,IAAA,aAA6B,kCAA7B,6BAA6B,EAAA;AACJ,IAAA,KAAqB,WAArB,qBAAqB,CAAA;AAC3DC,IAAAA,GAAG,mCAAM,WAAW,EAAjB;AACgC,IAAA,MAAmB,WAAnB,mBAAmB,CAAA;AACrC,IAAA,OAAoB,WAApB,oBAAoB,CAAA;AACJ,IAAA,cAA+B,WAA/B,+BAA+B,CAAA;AACvC,IAAA,WAAiC,WAAjC,iCAAiC,CAAA;AACtC,IAAA,SAAqB,WAArB,qBAAqB,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAErD,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,yBAAyB,CAAC,AAAsB,AAAC;AAEhF,MAAMC,YAAY,GAAG;IACnBC,SAAS,EAAE,6CAA6C;IACxDC,MAAM,EAAE,YAAY;CACrB,AAAC;AAEF,MAAMC,cAAc,GAAG,EAAE,GAAG,IAAI,AAAC;AAE1B,MAAMC,UAAU;IAOrBC,YAAoBC,WAAmB,EAAUC,IAAY,CAAE;aAA3CD,WAAmB,GAAnBA,WAAmB;aAAUC,IAAY,GAAZA,IAAY;aAFrDC,SAAS,GAAkB,IAAI;QAGrC,IAAI,CAACC,QAAQ,GAAG,IAAIC,cAAa,cAAA,CAACJ,WAAW,CAAC,CAAC;KAChD;IAED,AAAOK,YAAY,GAAkB;QACnC,OAAO,IAAI,CAACH,SAAS,CAAC;KACvB;IAED,2BAA2B,CAC3B,MAAMI,wBAAwB,GAAG;QAC/B,MAAMC,IAAI,GAAG,MAAMC,CAAAA,GAAAA,KAAY,AAAE,CAAA,aAAF,EAAE,AAAC;QAClC,IAAID,CAAAA,IAAI,QAAY,GAAhBA,KAAAA,CAAgB,GAAhBA,IAAI,CAAEE,UAAU,CAAA,KAAK,OAAO,EAAE;YAChC,MAAM,IAAIC,OAAY,aAAA,CAAC,aAAa,EAAE,qCAAqC,CAAC,CAAC;SAC9E;QACD,MAAMC,QAAQ,GAAGC,CAAAA,GAAAA,KAAmB,AAAM,CAAA,oBAAN,CAACL,IAAI,CAAC,AAAC;QAE3C,OAAO;YACL,sEAAsE;YACtE,MAAM,IAAI,CAACM,yBAAyB,EAAE;YACtCC,CAAAA,GAAAA,QAAO,AAAU,CAAA,QAAV,CAACH,QAAQ,CAAC;YACjB,yEAAyE;YACzE,IAAI,CAACV,IAAI;YACTP,YAAY,CAACE,MAAM;SACpB,CAACmB,IAAI,CAAC,GAAG,CAAC,CAAC;KACb;IAED,qDAAqD,CACrD,MAAMC,UAAU,CAAC,EAAEC,OAAO,CAAA,EAAwB,GAAG,EAAE,EAAiB;QACtE,+FAA+F;QAC/F,MAAM,IAAI,CAACd,QAAQ,CAACe,YAAY,CAAC;YAC/B,sHAAsH;YACtHC,oBAAoB,EAAE,IAAI;SAC3B,CAAC,CAAC;QAEH,iCAAiC;QACjC,IAAI,CAAE,MAAMC,CAAAA,GAAAA,WAAoB,AAAa,CAAA,qBAAb,CAAC;YAAC,IAAI,CAACnB,IAAI;SAAC,CAAC,AAAC,EAAE;YAC9C,8BAA8B;YAC9B,MAAM,IAAIS,OAAY,aAAA,CACpB,WAAW,EACX,CAAC,2FAA2F,CAAC,CAC9F,CAAC;SACH;QAED,IAAI,CAACR,SAAS,GAAG,MAAM,IAAI,CAACmB,oBAAoB,CAAC;YAAEJ,OAAO;SAAE,CAAC,CAAC;QAE9DzB,KAAK,CAAC,aAAa,EAAE,IAAI,CAACU,SAAS,CAAC,CAAC;QACrCX,GAAG,CAAC+B,GAAG,CAAC,eAAe,CAAC,CAAC;KAC1B;IAED,8CAA8C,CAC9C,MAAaC,SAAS,GAAkB;YAGhC,GAAmB;QAFzB/B,KAAK,CAAC,iBAAiB,CAAC,CAAC;QAEzB,OAAM,CAAA,GAAmB,GAAnB,IAAI,CAACW,QAAQ,CAACqB,GAAG,EAAE,SAAM,GAAzB,KAAA,CAAyB,GAAzB,GAAmB,CAAEC,IAAI,QAAI,GAA7B,KAAA,CAA6B,GAA7B,GAAmB,CAAEA,IAAI,EAAI,CAAA,CAAC;QACpC,IAAI,CAACvB,SAAS,GAAG,IAAI,CAAC;KACvB;IAED,2BAA2B,CAC3B,MAAMmB,oBAAoB,CACxBK,OAA6B,GAAG,EAAE,EAClCC,QAAgB,GAAG,CAAC,EACH;QACjB,gGAAgG;QAChG,MAAM,IAAI,CAACJ,SAAS,EAAE,CAAC;QAEvB,gDAAgD;QAChD,MAAMK,QAAQ,GAAG,MAAM,IAAI,CAACzB,QAAQ,CAACe,YAAY,CAAC;YAChDW,YAAY,EAAE,KAAK;YACnBC,WAAW,EAAE,KAAK;SACnB,CAAC,AAAC;YAOUJ,QAAe;QAL5B,4DAA4D;QAC5D,gEAAgE;QAChE,MAAMK,OAAO,GAAG,MAAMC,CAAAA,GAAAA,MAAkB,AAMvC,CAAA,mBANuC,CACtC,IAAM,IAAI,CAACC,2BAA2B,CAACL,QAAQ,EAAED,QAAQ,CAAC;QAAA,EAC1D;YACEV,OAAO,EAAES,CAAAA,QAAe,GAAfA,OAAO,CAACT,OAAO,YAAfS,QAAe,GAAI7B,cAAc;YAC1CqC,YAAY,EAAE,wCAAwC;SACvD,CACF,AAAC;QACF,IAAI,OAAOH,OAAO,KAAK,QAAQ,EAAE;YAC/B,OAAOA,OAAO,CAAC;SAChB;QAED,gCAAgC;QAChC,MAAMI,CAAAA,GAAAA,MAAU,AAAK,CAAA,WAAL,CAAC,GAAG,CAAC,CAAC;QAEtB,OAAO,IAAI,CAACd,oBAAoB,CAACK,OAAO,EAAEC,QAAQ,GAAG,CAAC,CAAC,CAAC;KACzD;IAED,MAAcM,2BAA2B,CACvCL,QAAuB,EACvBD,QAAgB,GAAG,CAAC,EACK;QACzB,IAAI;YACF,sBAAsB;YACtB,MAAMS,UAAU,GAAG9C,IAAI,CAACyB,IAAI,CAACsB,aAAY,QAAA,CAACC,YAAY,EAAE,EAAE,WAAW,CAAC,AAAC;YACvE9C,KAAK,CAAC,qBAAqB,EAAE4C,UAAU,CAAC,CAAC;YACzC,MAAMG,QAAQ,GAAG,MAAM,IAAI,CAACjC,wBAAwB,EAAE,AAAC;YACvDd,KAAK,CAAC,WAAW,EAAE+C,QAAQ,CAAC,CAAC;YAE7B,MAAMC,GAAG,GAAG,MAAMZ,QAAQ,CAACa,OAAO,CAAC;gBACjCC,SAAS,EAAEhD,YAAY,CAACC,SAAS;gBACjCgD,KAAK,EAAE,MAAM;gBACbJ,QAAQ;gBACRH,UAAU;gBACVQ,cAAc,EAACC,MAAM,EAAE;oBACrB,IAAIA,MAAM,KAAK,QAAQ,EAAE;wBACvBtD,GAAG,CAACuD,KAAK,CACP,2CAA2C,GACzC,uDAAuD,GACvD,0EAA0E,GAC1E,8BAA8B,CACjC,CAAC;qBACH,MAAM,IAAID,MAAM,KAAK,WAAW,EAAE;wBACjCtD,GAAG,CAAC+B,GAAG,CAAC,mBAAmB,CAAC,CAAC;qBAC9B;iBACF;gBACDrB,IAAI,EAAE,IAAI,CAACA,IAAI;aAChB,CAAC,AAAC;YACH,OAAOuC,GAAG,CAAC;SACZ,CAAC,OAAOM,KAAK,EAAO;YACnB,6BAA6B;YAC7B,IAAInB,QAAQ,IAAI,CAAC,EAAE;gBACjB,MAAM,IAAIjB,OAAY,aAAA,CAAC,eAAe,EAAEoC,KAAK,CAACC,QAAQ,EAAE,CAAC,CAAC;aAC3D;YAED,2BAA2B;YAC3B,IAAID,CAAAA,KAAK,QAAY,GAAjBA,KAAAA,CAAiB,GAAjBA,KAAK,CAAEE,UAAU,CAAA,KAAK,GAAG,EAAE;gBAC7B,oEAAoE;gBACpE,MAAM,IAAI,CAACC,4BAA4B,EAAE,CAAC;aAC3C;YACD,OAAO,KAAK,CAAC;SACd;KACF;IAED,MAAcpC,yBAAyB,GAAG;QACxC,MAAM,EAAEqC,aAAa,EAAEC,UAAU,CAAA,EAAE,GAAG,MAAMC,SAAe,gBAAA,CAACC,SAAS,CAAC,IAAI,CAACrD,WAAW,CAAC,AAAC;QACxF,IAAImD,UAAU,EAAE;YACd,OAAOA,UAAU,CAAC;SACnB;QACD,OAAO,MAAM,IAAI,CAACF,4BAA4B,EAAE,CAAC;KAClD;IAED,MAAMA,4BAA4B,GAAG;QACnC,MAAME,UAAU,GAAGG,OAAM,QAAA,CAACC,WAAW,CAAC,CAAC,CAAC,CAACR,QAAQ,CAAC,WAAW,CAAC,AAAC;QAC/D,MAAMK,SAAe,gBAAA,CAACI,QAAQ,CAAC,IAAI,CAACxD,WAAW,EAAE;YAAEkD,aAAa,EAAEC,UAAU;SAAE,CAAC,CAAC;QAChF3D,KAAK,CAAC,+BAA+B,EAAE2D,UAAU,CAAC,CAAC;QACnD,OAAOA,UAAU,CAAC;KACnB;CACF;QA7JYrD,UAAU,GAAVA,UAAU"}
|
|
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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"}
|
|
@@ -264,9 +264,12 @@ class BundlerDevServer {
|
|
|
264
264
|
}
|
|
265
265
|
/** Open the dev server in a runtime. */ async openPlatformAsync(launchTarget, resolver = {}) {
|
|
266
266
|
if (launchTarget === "desktop") {
|
|
267
|
-
const
|
|
267
|
+
const serverUrl = this.getDevServerUrl({
|
|
268
268
|
hostType: "localhost"
|
|
269
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;
|
|
270
273
|
await (0, _betterOpn).default(url);
|
|
271
274
|
return {
|
|
272
275
|
url
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/start/server/BundlerDevServer.ts"],"sourcesContent":["import { MessageSocket } from '@expo/dev-server';\nimport assert from 'assert';\nimport openBrowserAsync from 'better-opn';\nimport resolveFrom from 'resolve-from';\n\nimport { APISettings } from '../../api/settings';\nimport * as Log from '../../log';\nimport { FileNotifier } from '../../utils/FileNotifier';\nimport { resolveWithTimeout } from '../../utils/delay';\nimport { env } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport {\n BaseOpenInCustomProps,\n BaseResolveDeviceProps,\n PlatformManager,\n} from '../platforms/PlatformManager';\nimport { AsyncNgrok } from './AsyncNgrok';\nimport { DevelopmentSession } from './DevelopmentSession';\nimport { CreateURLOptions, UrlCreator } from './UrlCreator';\nimport { PlatformBundlers } from './platformBundlers';\n\nconst debug = require('debug')('expo:start:server:devServer') as typeof console.log;\n\nexport type ServerLike = {\n close(callback?: (err?: Error) => void): void;\n};\n\nexport type DevServerInstance = {\n /** Bundler dev server instance. */\n server: ServerLike;\n /** Dev server URL location properties. */\n location: {\n url: string;\n port: number;\n protocol: 'http' | 'https';\n host?: string;\n };\n /** Additional middleware that's attached to the `server`. */\n middleware: any;\n /** Message socket for communicating with the runtime. */\n messageSocket: MessageSocket;\n};\n\nexport interface BundlerStartOptions {\n /** Should the dev server use `https` protocol. */\n https?: boolean;\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Is dev client enabled. */\n devClient?: boolean;\n /** Should run dev servers with clean caches. */\n resetDevServer?: boolean;\n /** Which manifest type to serve. */\n forceManifestType?: 'expo-updates' | 'classic';\n /** Code signing private key path (defaults to same directory as certificate) */\n privateKeyPath?: string;\n\n /** Max amount of workers (threads) to use with Metro bundler, defaults to undefined for max workers. */\n maxWorkers?: number;\n /** Port to start the dev server on. */\n port?: number;\n\n /** Should start a headless dev server e.g. mock representation to approximate info from a server running in a different process. */\n headless?: boolean;\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n\n // Webpack options\n /** Should modify and create PWA icons. */\n isImageEditingEnabled?: boolean;\n\n location: CreateURLOptions;\n}\n\nconst PLATFORM_MANAGERS = {\n simulator: () =>\n require('../platforms/ios/ApplePlatformManager')\n .ApplePlatformManager as typeof import('../platforms/ios/ApplePlatformManager').ApplePlatformManager,\n emulator: () =>\n require('../platforms/android/AndroidPlatformManager')\n .AndroidPlatformManager as typeof import('../platforms/android/AndroidPlatformManager').AndroidPlatformManager,\n};\n\nconst MIDDLEWARES = {\n classic: () =>\n require('./middleware/ClassicManifestMiddleware')\n .ClassicManifestMiddleware as typeof import('./middleware/ClassicManifestMiddleware').ClassicManifestMiddleware,\n 'expo-updates': () =>\n require('./middleware/ExpoGoManifestHandlerMiddleware')\n .ExpoGoManifestHandlerMiddleware as typeof import('./middleware/ExpoGoManifestHandlerMiddleware').ExpoGoManifestHandlerMiddleware,\n};\n\nexport abstract class BundlerDevServer {\n /** Name of the bundler. */\n abstract get name(): string;\n\n /** Ngrok instance for managing tunnel connections. */\n protected ngrok: AsyncNgrok | null = null;\n /** Interfaces with the Expo 'Development Session' API. */\n protected devSession: DevelopmentSession | null = null;\n /** Http server and related info. */\n protected instance: DevServerInstance | null = null;\n /** Native platform interfaces for opening projects. */\n private platformManagers: Record<string, PlatformManager<any>> = {};\n /** Manages the creation of dev server URLs. */\n protected urlCreator?: UrlCreator | null = null;\n\n constructor(\n /** Project root folder. */\n public projectRoot: string,\n /** A mapping of bundlers to platforms. */\n public platformBundlers: PlatformBundlers,\n // TODO: Replace with custom scheme maybe...\n public isDevClient?: boolean\n ) {}\n\n protected setInstance(instance: DevServerInstance) {\n this.instance = instance;\n }\n\n /** Get the manifest middleware function. */\n protected async getManifestMiddlewareAsync(\n options: Pick<\n BundlerStartOptions,\n 'minify' | 'mode' | 'forceManifestType' | 'privateKeyPath'\n > = {}\n ) {\n const manifestType = options.forceManifestType || 'classic';\n assert(manifestType in MIDDLEWARES, `Manifest middleware for type '${manifestType}' not found`);\n const Middleware = MIDDLEWARES[manifestType]();\n\n const urlCreator = this.getUrlCreator();\n const middleware = new Middleware(this.projectRoot, {\n constructUrl: urlCreator.constructUrl.bind(urlCreator),\n mode: options.mode,\n minify: options.minify,\n isNativeWebpack: this.name === 'webpack' && this.isTargetingNative(),\n privateKeyPath: options.privateKeyPath,\n });\n return middleware.getHandler();\n }\n\n /** Start the dev server using settings defined in the start command. */\n public async startAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n await this.stopAsync();\n\n let instance: DevServerInstance;\n if (options.headless) {\n instance = await this.startHeadlessAsync(options);\n } else {\n instance = await this.startImplementationAsync(options);\n }\n\n this.setInstance(instance);\n await this.postStartAsync(options);\n return instance;\n }\n\n protected abstract startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance>;\n\n /**\n * Creates a mock server representation that can be used to estimate URLs for a server started in another process.\n * This is used for the run commands where you can reuse the server from a previous run.\n */\n private async startHeadlessAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n if (!options.port)\n throw new CommandError('HEADLESS_SERVER', 'headless dev server requires a port option');\n this.urlCreator = this.getUrlCreator(options);\n\n return {\n // Create a mock server\n server: {\n close: () => {\n this.instance = null;\n },\n },\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware: {},\n messageSocket: {\n broadcast: () => {\n throw new CommandError('HEADLESS_SERVER', 'Cannot broadcast messages to headless server');\n },\n },\n };\n }\n\n /**\n * Runs after the `startAsync` function, performing any additional common operations.\n * You can assume the dev server is started by the time this function is called.\n */\n protected async postStartAsync(options: BundlerStartOptions) {\n if (\n options.location.hostType === 'tunnel' &&\n !APISettings.isOffline &&\n // This is a hack to prevent using tunnel on web since we block it upstream for some reason.\n this.isTargetingNative()\n ) {\n await this._startTunnelAsync();\n }\n await this.startDevSessionAsync();\n\n this.watchConfig();\n }\n\n protected abstract getConfigModuleIds(): string[];\n\n protected watchConfig() {\n const notifier = new FileNotifier(this.projectRoot, this.getConfigModuleIds());\n notifier.startObserving();\n }\n\n /** Create ngrok instance and start the tunnel server. Exposed for testing. */\n public async _startTunnelAsync(): Promise<AsyncNgrok | null> {\n const port = this.getInstance()?.location.port;\n if (!port) return null;\n debug('[ngrok] connect to port: ' + port);\n this.ngrok = new AsyncNgrok(this.projectRoot, port);\n await this.ngrok.startAsync();\n return this.ngrok;\n }\n\n protected async startDevSessionAsync() {\n // This is used to make Expo Go open the project in either Expo Go, or the web browser.\n // Must come after ngrok (`startTunnelAsync`) setup.\n\n if (this.devSession) {\n this.devSession.stopNotifying();\n }\n\n this.devSession = new DevelopmentSession(\n this.projectRoot,\n // This URL will be used on external devices so the computer IP won't be relevant.\n this.isTargetingNative()\n ? this.getNativeRuntimeUrl()\n : this.getDevServerUrl({ hostType: 'localhost' }),\n () => {\n // TODO: This appears to be happening consistently after an hour.\n // We should investigate why this is happening and fix it on our servers.\n // Log.error(\n // chalk.red(\n // '\\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.'\n // )\n // );\n // Log.exception(error);\n this.devSession?.closeAsync().catch((error) => {\n debug('[dev-session] error closing: ' + error.message);\n });\n }\n );\n\n await this.devSession.startAsync({\n runtime: this.isTargetingNative() ? 'native' : 'web',\n });\n }\n\n public isTargetingNative() {\n // Temporary hack while we implement multi-bundler dev server proxy.\n return true;\n }\n\n public isTargetingWeb() {\n return this.platformBundlers.web === this.name;\n }\n\n /**\n * Sends a message over web sockets to any connected device,\n * does nothing when the dev server is not running.\n *\n * @param method name of the command. In RN projects `reload`, and `devMenu` are available. In Expo Go, `sendDevCommand` is available.\n * @param params\n */\n public broadcastMessage(\n method: 'reload' | 'devMenu' | 'sendDevCommand',\n params?: Record<string, any>\n ) {\n this.getInstance()?.messageSocket.broadcast(method, params);\n }\n\n /** Get the running dev server instance. */\n public getInstance() {\n return this.instance;\n }\n\n /** Stop the running dev server instance. */\n async stopAsync() {\n // Stop the dev session timer and tell Expo API to remove dev session.\n await this.devSession?.closeAsync();\n\n // Stop ngrok if running.\n await this.ngrok?.stopAsync().catch((e) => {\n Log.error(`Error stopping ngrok:`);\n Log.exception(e);\n });\n\n return resolveWithTimeout(\n () =>\n new Promise<void>((resolve, reject) => {\n // Close the server.\n debug(`Stopping dev server (bundler: ${this.name})`);\n\n if (this.instance?.server) {\n this.instance.server.close((error) => {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n } else {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n resolve();\n }\n }),\n {\n // NOTE(Bacon): Metro dev server doesn't seem to be closing in time.\n timeout: 1000,\n errorMessage: `Timeout waiting for '${this.name}' dev server to close`,\n }\n );\n }\n\n protected getUrlCreator(options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}) {\n if (!this.urlCreator) {\n assert(options?.port, 'Dev server instance not found');\n this.urlCreator = new UrlCreator(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n }\n return this.urlCreator;\n }\n\n public getNativeRuntimeUrl(opts: Partial<CreateURLOptions> = {}) {\n return this.isDevClient\n ? this.getUrlCreator().constructDevClientUrl(opts) ?? this.getDevServerUrl()\n : this.getUrlCreator().constructUrl({ ...opts, scheme: 'exp' });\n }\n\n /** Get the URL for the running instance of the dev server. */\n public getDevServerUrl(options: { hostType?: 'localhost' } = {}): string | null {\n const instance = this.getInstance();\n if (!instance?.location) {\n return null;\n }\n const { location } = instance;\n if (options.hostType === 'localhost') {\n return `${location.protocol}://localhost:${location.port}`;\n }\n return location.url ?? null;\n }\n\n /** Get the tunnel URL from ngrok. */\n public getTunnelUrl(): string | null {\n return this.ngrok?.getActiveUrl() ?? null;\n }\n\n /** Open the dev server in a runtime. */\n public async openPlatformAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS | 'desktop',\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n if (launchTarget === 'desktop') {\n const url = this.getDevServerUrl({ hostType: 'localhost' });\n await openBrowserAsync(url!);\n return { url };\n }\n\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime }, resolver);\n }\n\n /** Open the dev server in a runtime. */\n public async openCustomRuntimeAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS,\n launchProps: Partial<BaseOpenInCustomProps> = {},\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n if (runtime !== 'custom') {\n throw new CommandError(\n `dev server cannot open custom runtimes either because it does not target native platforms or because it is not targeting dev clients. (target: ${runtime})`\n );\n }\n\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime: 'custom', props: launchProps }, resolver);\n }\n\n /** Get the URL for opening in Expo Go. */\n protected getExpoGoUrl(): string {\n return this.getUrlCreator().constructUrl({ scheme: 'exp' });\n }\n\n /** Should use the interstitial page for selecting which runtime to use. */\n protected isRedirectPageEnabled(): boolean {\n return (\n !env.EXPO_NO_REDIRECT_PAGE &&\n // if user passed --dev-client flag, skip interstitial page\n !this.isDevClient &&\n // Checks if dev client is installed.\n !!resolveFrom.silent(this.projectRoot, 'expo-dev-client')\n );\n }\n\n /** Get the redirect URL when redirecting is enabled. */\n public getRedirectUrl(platform: keyof typeof PLATFORM_MANAGERS | null = null): string | null {\n if (!this.isRedirectPageEnabled()) {\n debug('Redirect page is disabled');\n return null;\n }\n\n return (\n this.getUrlCreator().constructLoadingUrl(\n {},\n platform === 'emulator' ? 'android' : platform === 'simulator' ? 'ios' : null\n ) ?? null\n );\n }\n\n protected async getPlatformManagerAsync(platform: keyof typeof PLATFORM_MANAGERS) {\n if (!this.platformManagers[platform]) {\n const Manager = PLATFORM_MANAGERS[platform]();\n const port = this.getInstance()?.location.port;\n if (!port || !this.urlCreator) {\n throw new CommandError(\n 'DEV_SERVER',\n 'Cannot interact with native platforms until dev server has started'\n );\n }\n debug(`Creating platform manager (platform: ${platform}, port: ${port})`);\n this.platformManagers[platform] = new Manager(this.projectRoot, port, {\n getCustomRuntimeUrl: this.urlCreator.constructDevClientUrl.bind(this.urlCreator),\n getExpoGoUrl: this.getExpoGoUrl.bind(this),\n getRedirectUrl: this.getRedirectUrl.bind(this, platform),\n getDevServerUrl: this.getDevServerUrl.bind(this, { hostType: 'localhost' }),\n });\n }\n return this.platformManagers[platform];\n }\n}\n"],"names":["Log","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","MIDDLEWARES","classic","ClassicManifestMiddleware","ExpoGoManifestHandlerMiddleware","BundlerDevServer","constructor","projectRoot","platformBundlers","isDevClient","ngrok","devSession","instance","platformManagers","urlCreator","setInstance","getManifestMiddlewareAsync","options","manifestType","forceManifestType","assert","Middleware","getUrlCreator","middleware","constructUrl","bind","mode","minify","isNativeWebpack","name","isTargetingNative","privateKeyPath","getHandler","startAsync","stopAsync","headless","startHeadlessAsync","startImplementationAsync","postStartAsync","port","CommandError","server","close","location","host","url","protocol","messageSocket","broadcast","hostType","APISettings","isOffline","_startTunnelAsync","startDevSessionAsync","watchConfig","notifier","FileNotifier","getConfigModuleIds","startObserving","getInstance","AsyncNgrok","stopNotifying","DevelopmentSession","getNativeRuntimeUrl","getDevServerUrl","closeAsync","catch","error","message","runtime","isTargetingWeb","web","broadcastMessage","method","params","e","exception","resolveWithTimeout","Promise","resolve","reject","timeout","errorMessage","UrlCreator","getTunnelUrl","opts","constructDevClientUrl","scheme","getActiveUrl","openPlatformAsync","launchTarget","resolver","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","env","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","Manager","getCustomRuntimeUrl"],"mappings":"AAAA;;;;AACmB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AACE,IAAA,UAAY,kCAAZ,YAAY,EAAA;AACjB,IAAA,YAAc,kCAAd,cAAc,EAAA;AAEV,IAAA,SAAoB,WAApB,oBAAoB,CAAA;AACpCA,IAAAA,GAAG,mCAAM,WAAW,EAAjB;AACc,IAAA,aAA0B,WAA1B,0BAA0B,CAAA;AACpB,IAAA,MAAmB,WAAnB,mBAAmB,CAAA;AAClC,IAAA,IAAiB,WAAjB,iBAAiB,CAAA;AACR,IAAA,OAAoB,WAApB,oBAAoB,CAAA;AAMtB,IAAA,WAAc,WAAd,cAAc,CAAA;AACN,IAAA,mBAAsB,WAAtB,sBAAsB,CAAA;AACZ,IAAA,WAAc,WAAd,cAAc,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG3D,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,6BAA6B,CAAC,AAAsB,AAAC;AAqDpF,MAAMC,iBAAiB,GAAG;IACxBC,SAAS,EAAE,IACTF,OAAO,CAAC,uCAAuC,CAAC,CAC7CG,oBAAoB;IAA+E;IACxGC,QAAQ,EAAE,IACRJ,OAAO,CAAC,6CAA6C,CAAC,CACnDK,sBAAsB;CAC5B,AAAC;AAEF,MAAMC,WAAW,GAAG;IAClBC,OAAO,EAAE,IACPP,OAAO,CAAC,wCAAwC,CAAC,CAC9CQ,yBAAyB;IAAqF;IACnH,cAAc,EAAE,IACdR,OAAO,CAAC,8CAA8C,CAAC,CACpDS,+BAA+B;CACrC,AAAC;AAEK,MAAeC,gBAAgB;IAepCC,YAESC,WAAmB,EAEnBC,gBAAkC,EAElCC,WAAqB,CAC5B;aALOF,WAAmB,GAAnBA,WAAmB;aAEnBC,gBAAkC,GAAlCA,gBAAkC;aAElCC,WAAqB,GAArBA,WAAqB;aAhBpBC,KAAK,GAAsB,IAAI;aAE/BC,UAAU,GAA8B,IAAI;aAE5CC,QAAQ,GAA6B,IAAI;aAE3CC,gBAAgB,GAAyC,EAAE;aAEzDC,UAAU,GAAuB,IAAI;KAS3C;IAEJ,AAAUC,WAAW,CAACH,QAA2B,EAAE;QACjD,IAAI,CAACA,QAAQ,GAAGA,QAAQ,CAAC;KAC1B;IAED,4CAA4C,CAC5C,MAAgBI,0BAA0B,CACxCC,OAGC,GAAG,EAAE,EACN;QACA,MAAMC,YAAY,GAAGD,OAAO,CAACE,iBAAiB,IAAI,SAAS,AAAC;QAC5DC,CAAAA,GAAAA,OAAM,AAAyF,CAAA,QAAzF,CAACF,YAAY,IAAIjB,WAAW,EAAE,CAAC,8BAA8B,EAAEiB,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;QAChG,MAAMG,UAAU,GAAGpB,WAAW,CAACiB,YAAY,CAAC,EAAE,AAAC;QAE/C,MAAMJ,UAAU,GAAG,IAAI,CAACQ,aAAa,EAAE,AAAC;QACxC,MAAMC,UAAU,GAAG,IAAIF,UAAU,CAAC,IAAI,CAACd,WAAW,EAAE;YAClDiB,YAAY,EAAEV,UAAU,CAACU,YAAY,CAACC,IAAI,CAACX,UAAU,CAAC;YACtDY,IAAI,EAAET,OAAO,CAACS,IAAI;YAClBC,MAAM,EAAEV,OAAO,CAACU,MAAM;YACtBC,eAAe,EAAE,IAAI,CAACC,IAAI,KAAK,SAAS,IAAI,IAAI,CAACC,iBAAiB,EAAE;YACpEC,cAAc,EAAEd,OAAO,CAACc,cAAc;SACvC,CAAC,AAAC;QACH,OAAOR,UAAU,CAACS,UAAU,EAAE,CAAC;KAChC;IAED,wEAAwE,CACxE,MAAaC,UAAU,CAAChB,OAA4B,EAA8B;QAChF,MAAM,IAAI,CAACiB,SAAS,EAAE,CAAC;QAEvB,IAAItB,QAAQ,AAAmB,AAAC;QAChC,IAAIK,OAAO,CAACkB,QAAQ,EAAE;YACpBvB,QAAQ,GAAG,MAAM,IAAI,CAACwB,kBAAkB,CAACnB,OAAO,CAAC,CAAC;SACnD,MAAM;YACLL,QAAQ,GAAG,MAAM,IAAI,CAACyB,wBAAwB,CAACpB,OAAO,CAAC,CAAC;SACzD;QAED,IAAI,CAACF,WAAW,CAACH,QAAQ,CAAC,CAAC;QAC3B,MAAM,IAAI,CAAC0B,cAAc,CAACrB,OAAO,CAAC,CAAC;QACnC,OAAOL,QAAQ,CAAC;KACjB;IAMD;;;KAGG,CACH,MAAcwB,kBAAkB,CAACnB,OAA4B,EAA8B;QACzF,IAAI,CAACA,OAAO,CAACsB,IAAI,EACf,MAAM,IAAIC,OAAY,aAAA,CAAC,iBAAiB,EAAE,4CAA4C,CAAC,CAAC;QAC1F,IAAI,CAAC1B,UAAU,GAAG,IAAI,CAACQ,aAAa,CAACL,OAAO,CAAC,CAAC;QAE9C,OAAO;YACL,uBAAuB;YACvBwB,MAAM,EAAE;gBACNC,KAAK,EAAE,IAAM;oBACX,IAAI,CAAC9B,QAAQ,GAAG,IAAI,CAAC;iBACtB;aACF;YACD+B,QAAQ,EAAE;gBACR,mDAAmD;gBACnDJ,IAAI,EAAEtB,OAAO,CAACsB,IAAI;gBAClB,kCAAkC;gBAClCK,IAAI,EAAE,WAAW;gBACjB,iDAAiD;gBACjDC,GAAG,EAAE,CAAC,iBAAiB,EAAE5B,OAAO,CAACsB,IAAI,CAAC,CAAC;gBACvCO,QAAQ,EAAE,MAAM;aACjB;YACDvB,UAAU,EAAE,EAAE;YACdwB,aAAa,EAAE;gBACbC,SAAS,EAAE,IAAM;oBACf,MAAM,IAAIR,OAAY,aAAA,CAAC,iBAAiB,EAAE,8CAA8C,CAAC,CAAC;iBAC3F;aACF;SACF,CAAC;KACH;IAED;;;KAGG,CACH,MAAgBF,cAAc,CAACrB,OAA4B,EAAE;QAC3D,IACEA,OAAO,CAAC0B,QAAQ,CAACM,QAAQ,KAAK,QAAQ,IACtC,CAACC,SAAW,YAAA,CAACC,SAAS,IACtB,4FAA4F;QAC5F,IAAI,CAACrB,iBAAiB,EAAE,EACxB;YACA,MAAM,IAAI,CAACsB,iBAAiB,EAAE,CAAC;SAChC;QACD,MAAM,IAAI,CAACC,oBAAoB,EAAE,CAAC;QAElC,IAAI,CAACC,WAAW,EAAE,CAAC;KACpB;IAID,AAAUA,WAAW,GAAG;QACtB,MAAMC,QAAQ,GAAG,IAAIC,aAAY,aAAA,CAAC,IAAI,CAACjD,WAAW,EAAE,IAAI,CAACkD,kBAAkB,EAAE,CAAC,AAAC;QAC/EF,QAAQ,CAACG,cAAc,EAAE,CAAC;KAC3B;IAED,8EAA8E,CAC9E,MAAaN,iBAAiB,GAA+B;YAC9C,GAAkB;QAA/B,MAAMb,IAAI,GAAG,CAAA,GAAkB,GAAlB,IAAI,CAACoB,WAAW,EAAE,SAAU,GAA5B,KAAA,CAA4B,GAA5B,GAAkB,CAAEhB,QAAQ,CAACJ,IAAI,AAAC;QAC/C,IAAI,CAACA,IAAI,EAAE,OAAO,IAAI,CAAC;QACvB7C,KAAK,CAAC,2BAA2B,GAAG6C,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC7B,KAAK,GAAG,IAAIkD,WAAU,WAAA,CAAC,IAAI,CAACrD,WAAW,EAAEgC,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC7B,KAAK,CAACuB,UAAU,EAAE,CAAC;QAC9B,OAAO,IAAI,CAACvB,KAAK,CAAC;KACnB;IAED,MAAgB2C,oBAAoB,GAAG;QACrC,uFAAuF;QACvF,oDAAoD;QAEpD,IAAI,IAAI,CAAC1C,UAAU,EAAE;YACnB,IAAI,CAACA,UAAU,CAACkD,aAAa,EAAE,CAAC;SACjC;QAED,IAAI,CAAClD,UAAU,GAAG,IAAImD,mBAAkB,mBAAA,CACtC,IAAI,CAACvD,WAAW,EAChB,kFAAkF;QAClF,IAAI,CAACuB,iBAAiB,EAAE,GACpB,IAAI,CAACiC,mBAAmB,EAAE,GAC1B,IAAI,CAACC,eAAe,CAAC;YAAEf,QAAQ,EAAE,WAAW;SAAE,CAAC,EACnD,IAAM;gBACJ,iEAAiE;YACjE,yEAAyE;YACzE,aAAa;YACb,eAAe;YACf,uMAAuM;YACvM,MAAM;YACN,KAAK;YACL,wBAAwB;YACxB,GAAe;YAAf,CAAA,GAAe,GAAf,IAAI,CAACtC,UAAU,SAAY,GAA3B,KAAA,CAA2B,GAA3B,GAAe,CAAEsD,UAAU,EAAE,CAACC,KAAK,CAAC,CAACC,KAAK,GAAK;gBAC7CzE,KAAK,CAAC,+BAA+B,GAAGyE,KAAK,CAACC,OAAO,CAAC,CAAC;aACxD,CAAC,CAAC;SACJ,CACF,CAAC;QAEF,MAAM,IAAI,CAACzD,UAAU,CAACsB,UAAU,CAAC;YAC/BoC,OAAO,EAAE,IAAI,CAACvC,iBAAiB,EAAE,GAAG,QAAQ,GAAG,KAAK;SACrD,CAAC,CAAC;KACJ;IAED,AAAOA,iBAAiB,GAAG;QACzB,oEAAoE;QACpE,OAAO,IAAI,CAAC;KACb;IAED,AAAOwC,cAAc,GAAG;QACtB,OAAO,IAAI,CAAC9D,gBAAgB,CAAC+D,GAAG,KAAK,IAAI,CAAC1C,IAAI,CAAC;KAChD;IAED;;;;;;KAMG,CACH,AAAO2C,gBAAgB,CACrBC,MAA+C,EAC/CC,MAA4B,EAC5B;YACA,GAAkB;QAAlB,CAAA,GAAkB,GAAlB,IAAI,CAACf,WAAW,EAAE,SAAe,GAAjC,KAAA,CAAiC,GAAjC,GAAkB,CAAEZ,aAAa,CAACC,SAAS,CAACyB,MAAM,EAAEC,MAAM,CAAC,CAAC;KAC7D;IAED,2CAA2C,CAC3C,AAAOf,WAAW,GAAG;QACnB,OAAO,IAAI,CAAC/C,QAAQ,CAAC;KACtB;IAED,4CAA4C,CAC5C,MAAMsB,SAAS,GAAG;YAEV,IAAe,EAGf,IAAU;QAJhB,sEAAsE;QACtE,OAAM,CAAA,IAAe,GAAf,IAAI,CAACvB,UAAU,SAAY,GAA3B,KAAA,CAA2B,GAA3B,IAAe,CAAEsD,UAAU,EAAE,CAAA,CAAC;QAEpC,yBAAyB;QACzB,MAAM,CAAA,CAAA,IAAU,GAAV,IAAI,CAACvD,KAAK,SAAW,GAArB,KAAA,CAAqB,GAArB,IAAU,CAAEwB,SAAS,EAAE,CAACgC,KAAK,CAAC,CAACS,CAAC,GAAK;YACzClF,GAAG,CAAC0E,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACnC1E,GAAG,CAACmF,SAAS,CAACD,CAAC,CAAC,CAAC;SAClB,CAAC,CAAA,CAAC;QAEH,OAAOE,CAAAA,GAAAA,MAAkB,AA2BxB,CAAA,mBA3BwB,CACvB;YACE,OAAA,IAAIC,OAAO,CAAO,CAACC,OAAO,EAAEC,MAAM,GAAK;oBAIjC,GAAa;gBAHjB,oBAAoB;gBACpBtF,KAAK,CAAC,CAAC,8BAA8B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAErD,IAAI,CAAA,GAAa,GAAb,IAAI,CAACjB,QAAQ,SAAQ,GAArB,KAAA,CAAqB,GAArB,GAAa,CAAE6B,MAAM,EAAE;oBACzB,IAAI,CAAC7B,QAAQ,CAAC6B,MAAM,CAACC,KAAK,CAAC,CAACyB,KAAK,GAAK;wBACpCzE,KAAK,CAAC,CAAC,6BAA6B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;wBACpD,IAAI,CAACjB,QAAQ,GAAG,IAAI,CAAC;wBACrB,IAAIuD,KAAK,EAAE;4BACTa,MAAM,CAACb,KAAK,CAAC,CAAC;yBACf,MAAM;4BACLY,OAAO,EAAE,CAAC;yBACX;qBACF,CAAC,CAAC;iBACJ,MAAM;oBACLrF,KAAK,CAAC,CAAC,6BAA6B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpD,IAAI,CAACjB,QAAQ,GAAG,IAAI,CAAC;oBACrBmE,OAAO,EAAE,CAAC;iBACX;aACF,CAAC,CAAA;SAAA,EACJ;YACE,oEAAoE;YACpEE,OAAO,EAAE,IAAI;YACbC,YAAY,EAAE,CAAC,qBAAqB,EAAE,IAAI,CAACrD,IAAI,CAAC,qBAAqB,CAAC;SACvE,CACF,CAAC;KACH;IAED,AAAUP,aAAa,CAACL,OAAgE,GAAG,EAAE,EAAE;QAC7F,IAAI,CAAC,IAAI,CAACH,UAAU,EAAE;YACpBM,CAAAA,GAAAA,OAAM,AAAgD,CAAA,QAAhD,CAACH,OAAO,QAAM,GAAbA,KAAAA,CAAa,GAAbA,OAAO,CAAEsB,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACvD,IAAI,CAACzB,UAAU,GAAG,IAAIqE,WAAU,WAAA,CAAClE,OAAO,CAAC0B,QAAQ,EAAE;gBACjDJ,IAAI,EAAEtB,OAAO,CAACsB,IAAI;gBAClB6C,YAAY,EAAE,IAAI,CAACA,YAAY,CAAC3D,IAAI,CAAC,IAAI,CAAC;aAC3C,CAAC,CAAC;SACJ;QACD,OAAO,IAAI,CAACX,UAAU,CAAC;KACxB;IAED,AAAOiD,mBAAmB,CAACsB,IAA+B,GAAG,EAAE,EAAE;YAE3D,GAAgD;QADpD,OAAO,IAAI,CAAC5E,WAAW,GACnB,CAAA,GAAgD,GAAhD,IAAI,CAACa,aAAa,EAAE,CAACgE,qBAAqB,CAACD,IAAI,CAAC,YAAhD,GAAgD,GAAI,IAAI,CAACrB,eAAe,EAAE,GAC1E,IAAI,CAAC1C,aAAa,EAAE,CAACE,YAAY,CAAC;YAAE,GAAG6D,IAAI;YAAEE,MAAM,EAAE,KAAK;SAAE,CAAC,CAAC;KACnE;IAED,8DAA8D,CAC9D,AAAOvB,eAAe,CAAC/C,OAAmC,GAAG,EAAE,EAAiB;QAC9E,MAAML,QAAQ,GAAG,IAAI,CAAC+C,WAAW,EAAE,AAAC;QACpC,IAAI,CAAC/C,CAAAA,QAAQ,QAAU,GAAlBA,KAAAA,CAAkB,GAAlBA,QAAQ,CAAE+B,QAAQ,CAAA,EAAE;YACvB,OAAO,IAAI,CAAC;SACb;QACD,MAAM,EAAEA,QAAQ,CAAA,EAAE,GAAG/B,QAAQ,AAAC;QAC9B,IAAIK,OAAO,CAACgC,QAAQ,KAAK,WAAW,EAAE;YACpC,OAAO,CAAC,EAAEN,QAAQ,CAACG,QAAQ,CAAC,aAAa,EAAEH,QAAQ,CAACJ,IAAI,CAAC,CAAC,CAAC;SAC5D;YACMI,IAAY;QAAnB,OAAOA,CAAAA,IAAY,GAAZA,QAAQ,CAACE,GAAG,YAAZF,IAAY,GAAI,IAAI,CAAC;KAC7B;IAED,qCAAqC,CACrC,AAAOyC,YAAY,GAAkB;YAC5B,GAAU;YAAV,IAA0B;QAAjC,OAAO,CAAA,IAA0B,GAA1B,CAAA,GAAU,GAAV,IAAI,CAAC1E,KAAK,SAAc,GAAxB,KAAA,CAAwB,GAAxB,GAAU,CAAE8E,YAAY,EAAE,YAA1B,IAA0B,GAAI,IAAI,CAAC;KAC3C;IAED,wCAAwC,CACxC,MAAaC,iBAAiB,CAC5BC,YAAwD,EACxDC,QAAqC,GAAG,EAAE,EAC1C;QACA,IAAID,YAAY,KAAK,SAAS,EAAE;YAC9B,MAAM7C,GAAG,GAAG,IAAI,CAACmB,eAAe,CAAC;gBAAEf,QAAQ,EAAE,WAAW;aAAE,CAAC,AAAC;YAC5D,MAAM2C,CAAAA,GAAAA,UAAgB,AAAM,CAAA,QAAN,CAAC/C,GAAG,CAAE,CAAC;YAC7B,OAAO;gBAAEA,GAAG;aAAE,CAAC;SAChB;QAED,MAAMwB,OAAO,GAAG,IAAI,CAACvC,iBAAiB,EAAE,GAAI,IAAI,CAACrB,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAI,KAAK,AAAC;QAC1F,MAAMoF,OAAO,GAAG,MAAM,IAAI,CAACC,uBAAuB,CAACJ,YAAY,CAAC,AAAC;QACjE,OAAOG,OAAO,CAACE,SAAS,CAAC;YAAE1B,OAAO;SAAE,EAAEsB,QAAQ,CAAC,CAAC;KACjD;IAED,wCAAwC,CACxC,MAAaK,sBAAsB,CACjCN,YAA4C,EAC5CO,WAA2C,GAAG,EAAE,EAChDN,QAAqC,GAAG,EAAE,EAC1C;QACA,MAAMtB,OAAO,GAAG,IAAI,CAACvC,iBAAiB,EAAE,GAAI,IAAI,CAACrB,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAI,KAAK,AAAC;QAC1F,IAAI4D,OAAO,KAAK,QAAQ,EAAE;YACxB,MAAM,IAAI7B,OAAY,aAAA,CACpB,CAAC,+IAA+I,EAAE6B,OAAO,CAAC,CAAC,CAAC,CAC7J,CAAC;SACH;QAED,MAAMwB,OAAO,GAAG,MAAM,IAAI,CAACC,uBAAuB,CAACJ,YAAY,CAAC,AAAC;QACjE,OAAOG,OAAO,CAACE,SAAS,CAAC;YAAE1B,OAAO,EAAE,QAAQ;YAAE6B,KAAK,EAAED,WAAW;SAAE,EAAEN,QAAQ,CAAC,CAAC;KAC/E;IAED,0CAA0C,CAC1C,AAAUQ,YAAY,GAAW;QAC/B,OAAO,IAAI,CAAC7E,aAAa,EAAE,CAACE,YAAY,CAAC;YAAE+D,MAAM,EAAE,KAAK;SAAE,CAAC,CAAC;KAC7D;IAED,2EAA2E,CAC3E,AAAUa,qBAAqB,GAAY;QACzC,OACE,CAACC,IAAG,IAAA,CAACC,qBAAqB,IAC1B,2DAA2D;QAC3D,CAAC,IAAI,CAAC7F,WAAW,IACjB,qCAAqC;QACrC,CAAC,CAAC8F,YAAW,QAAA,CAACC,MAAM,CAAC,IAAI,CAACjG,WAAW,EAAE,iBAAiB,CAAC,CACzD;KACH;IAED,wDAAwD,CACxD,AAAOkG,cAAc,CAACC,QAA+C,GAAG,IAAI,EAAiB;QAC3F,IAAI,CAAC,IAAI,CAACN,qBAAqB,EAAE,EAAE;YACjC1G,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;SACb;YAGC,GAGC;QAJH,OACE,CAAA,GAGC,GAHD,IAAI,CAAC4B,aAAa,EAAE,CAACqF,mBAAmB,CACtC,EAAE,EACFD,QAAQ,KAAK,UAAU,GAAG,SAAS,GAAGA,QAAQ,KAAK,WAAW,GAAG,KAAK,GAAG,IAAI,CAC9E,YAHD,GAGC,GAAI,IAAI,CACT;KACH;IAED,MAAgBZ,uBAAuB,CAACY,QAAwC,EAAE;QAChF,IAAI,CAAC,IAAI,CAAC7F,gBAAgB,CAAC6F,QAAQ,CAAC,EAAE;gBAEvB,GAAkB;YAD/B,MAAME,OAAO,GAAGhH,iBAAiB,CAAC8G,QAAQ,CAAC,EAAE,AAAC;YAC9C,MAAMnE,IAAI,GAAG,CAAA,GAAkB,GAAlB,IAAI,CAACoB,WAAW,EAAE,SAAU,GAA5B,KAAA,CAA4B,GAA5B,GAAkB,CAAEhB,QAAQ,CAACJ,IAAI,AAAC;YAC/C,IAAI,CAACA,IAAI,IAAI,CAAC,IAAI,CAACzB,UAAU,EAAE;gBAC7B,MAAM,IAAI0B,OAAY,aAAA,CACpB,YAAY,EACZ,oEAAoE,CACrE,CAAC;aACH;YACD9C,KAAK,CAAC,CAAC,qCAAqC,EAAEgH,QAAQ,CAAC,QAAQ,EAAEnE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC1B,gBAAgB,CAAC6F,QAAQ,CAAC,GAAG,IAAIE,OAAO,CAAC,IAAI,CAACrG,WAAW,EAAEgC,IAAI,EAAE;gBACpEsE,mBAAmB,EAAE,IAAI,CAAC/F,UAAU,CAACwE,qBAAqB,CAAC7D,IAAI,CAAC,IAAI,CAACX,UAAU,CAAC;gBAChFqF,YAAY,EAAE,IAAI,CAACA,YAAY,CAAC1E,IAAI,CAAC,IAAI,CAAC;gBAC1CgF,cAAc,EAAE,IAAI,CAACA,cAAc,CAAChF,IAAI,CAAC,IAAI,EAAEiF,QAAQ,CAAC;gBACxD1C,eAAe,EAAE,IAAI,CAACA,eAAe,CAACvC,IAAI,CAAC,IAAI,EAAE;oBAAEwB,QAAQ,EAAE,WAAW;iBAAE,CAAC;aAC5E,CAAC,CAAC;SACJ;QACD,OAAO,IAAI,CAACpC,gBAAgB,CAAC6F,QAAQ,CAAC,CAAC;KACxC;CACF;QAzWqBrG,gBAAgB,GAAhBA,gBAAgB"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/start/server/BundlerDevServer.ts"],"sourcesContent":["import { MessageSocket } from '@expo/dev-server';\nimport assert from 'assert';\nimport openBrowserAsync from 'better-opn';\nimport resolveFrom from 'resolve-from';\n\nimport { APISettings } from '../../api/settings';\nimport * as Log from '../../log';\nimport { FileNotifier } from '../../utils/FileNotifier';\nimport { resolveWithTimeout } from '../../utils/delay';\nimport { env } from '../../utils/env';\nimport { CommandError } from '../../utils/errors';\nimport {\n BaseOpenInCustomProps,\n BaseResolveDeviceProps,\n PlatformManager,\n} from '../platforms/PlatformManager';\nimport { AsyncNgrok } from './AsyncNgrok';\nimport { DevelopmentSession } from './DevelopmentSession';\nimport { CreateURLOptions, UrlCreator } from './UrlCreator';\nimport { PlatformBundlers } from './platformBundlers';\n\nconst debug = require('debug')('expo:start:server:devServer') as typeof console.log;\n\nexport type ServerLike = {\n close(callback?: (err?: Error) => void): void;\n};\n\nexport type DevServerInstance = {\n /** Bundler dev server instance. */\n server: ServerLike;\n /** Dev server URL location properties. */\n location: {\n url: string;\n port: number;\n protocol: 'http' | 'https';\n host?: string;\n };\n /** Additional middleware that's attached to the `server`. */\n middleware: any;\n /** Message socket for communicating with the runtime. */\n messageSocket: MessageSocket;\n};\n\nexport interface BundlerStartOptions {\n /** Should the dev server use `https` protocol. */\n https?: boolean;\n /** Should start the dev servers in development mode (minify). */\n mode?: 'development' | 'production';\n /** Is dev client enabled. */\n devClient?: boolean;\n /** Should run dev servers with clean caches. */\n resetDevServer?: boolean;\n /** Which manifest type to serve. */\n forceManifestType?: 'expo-updates' | 'classic';\n /** Code signing private key path (defaults to same directory as certificate) */\n privateKeyPath?: string;\n\n /** Max amount of workers (threads) to use with Metro bundler, defaults to undefined for max workers. */\n maxWorkers?: number;\n /** Port to start the dev server on. */\n port?: number;\n\n /** Should start a headless dev server e.g. mock representation to approximate info from a server running in a different process. */\n headless?: boolean;\n /** Should instruct the bundler to create minified bundles. */\n minify?: boolean;\n\n // Webpack options\n /** Should modify and create PWA icons. */\n isImageEditingEnabled?: boolean;\n\n location: CreateURLOptions;\n}\n\nconst PLATFORM_MANAGERS = {\n simulator: () =>\n require('../platforms/ios/ApplePlatformManager')\n .ApplePlatformManager as typeof import('../platforms/ios/ApplePlatformManager').ApplePlatformManager,\n emulator: () =>\n require('../platforms/android/AndroidPlatformManager')\n .AndroidPlatformManager as typeof import('../platforms/android/AndroidPlatformManager').AndroidPlatformManager,\n};\n\nconst MIDDLEWARES = {\n classic: () =>\n require('./middleware/ClassicManifestMiddleware')\n .ClassicManifestMiddleware as typeof import('./middleware/ClassicManifestMiddleware').ClassicManifestMiddleware,\n 'expo-updates': () =>\n require('./middleware/ExpoGoManifestHandlerMiddleware')\n .ExpoGoManifestHandlerMiddleware as typeof import('./middleware/ExpoGoManifestHandlerMiddleware').ExpoGoManifestHandlerMiddleware,\n};\n\nexport abstract class BundlerDevServer {\n /** Name of the bundler. */\n abstract get name(): string;\n\n /** Ngrok instance for managing tunnel connections. */\n protected ngrok: AsyncNgrok | null = null;\n /** Interfaces with the Expo 'Development Session' API. */\n protected devSession: DevelopmentSession | null = null;\n /** Http server and related info. */\n protected instance: DevServerInstance | null = null;\n /** Native platform interfaces for opening projects. */\n private platformManagers: Record<string, PlatformManager<any>> = {};\n /** Manages the creation of dev server URLs. */\n protected urlCreator?: UrlCreator | null = null;\n\n constructor(\n /** Project root folder. */\n public projectRoot: string,\n /** A mapping of bundlers to platforms. */\n public platformBundlers: PlatformBundlers,\n // TODO: Replace with custom scheme maybe...\n public isDevClient?: boolean\n ) {}\n\n protected setInstance(instance: DevServerInstance) {\n this.instance = instance;\n }\n\n /** Get the manifest middleware function. */\n protected async getManifestMiddlewareAsync(\n options: Pick<\n BundlerStartOptions,\n 'minify' | 'mode' | 'forceManifestType' | 'privateKeyPath'\n > = {}\n ) {\n const manifestType = options.forceManifestType || 'classic';\n assert(manifestType in MIDDLEWARES, `Manifest middleware for type '${manifestType}' not found`);\n const Middleware = MIDDLEWARES[manifestType]();\n\n const urlCreator = this.getUrlCreator();\n const middleware = new Middleware(this.projectRoot, {\n constructUrl: urlCreator.constructUrl.bind(urlCreator),\n mode: options.mode,\n minify: options.minify,\n isNativeWebpack: this.name === 'webpack' && this.isTargetingNative(),\n privateKeyPath: options.privateKeyPath,\n });\n return middleware.getHandler();\n }\n\n /** Start the dev server using settings defined in the start command. */\n public async startAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n await this.stopAsync();\n\n let instance: DevServerInstance;\n if (options.headless) {\n instance = await this.startHeadlessAsync(options);\n } else {\n instance = await this.startImplementationAsync(options);\n }\n\n this.setInstance(instance);\n await this.postStartAsync(options);\n return instance;\n }\n\n protected abstract startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance>;\n\n /**\n * Creates a mock server representation that can be used to estimate URLs for a server started in another process.\n * This is used for the run commands where you can reuse the server from a previous run.\n */\n private async startHeadlessAsync(options: BundlerStartOptions): Promise<DevServerInstance> {\n if (!options.port)\n throw new CommandError('HEADLESS_SERVER', 'headless dev server requires a port option');\n this.urlCreator = this.getUrlCreator(options);\n\n return {\n // Create a mock server\n server: {\n close: () => {\n this.instance = null;\n },\n },\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware: {},\n messageSocket: {\n broadcast: () => {\n throw new CommandError('HEADLESS_SERVER', 'Cannot broadcast messages to headless server');\n },\n },\n };\n }\n\n /**\n * Runs after the `startAsync` function, performing any additional common operations.\n * You can assume the dev server is started by the time this function is called.\n */\n protected async postStartAsync(options: BundlerStartOptions) {\n if (\n options.location.hostType === 'tunnel' &&\n !APISettings.isOffline &&\n // This is a hack to prevent using tunnel on web since we block it upstream for some reason.\n this.isTargetingNative()\n ) {\n await this._startTunnelAsync();\n }\n await this.startDevSessionAsync();\n\n this.watchConfig();\n }\n\n protected abstract getConfigModuleIds(): string[];\n\n protected watchConfig() {\n const notifier = new FileNotifier(this.projectRoot, this.getConfigModuleIds());\n notifier.startObserving();\n }\n\n /** Create ngrok instance and start the tunnel server. Exposed for testing. */\n public async _startTunnelAsync(): Promise<AsyncNgrok | null> {\n const port = this.getInstance()?.location.port;\n if (!port) return null;\n debug('[ngrok] connect to port: ' + port);\n this.ngrok = new AsyncNgrok(this.projectRoot, port);\n await this.ngrok.startAsync();\n return this.ngrok;\n }\n\n protected async startDevSessionAsync() {\n // This is used to make Expo Go open the project in either Expo Go, or the web browser.\n // Must come after ngrok (`startTunnelAsync`) setup.\n\n if (this.devSession) {\n this.devSession.stopNotifying();\n }\n\n this.devSession = new DevelopmentSession(\n this.projectRoot,\n // This URL will be used on external devices so the computer IP won't be relevant.\n this.isTargetingNative()\n ? this.getNativeRuntimeUrl()\n : this.getDevServerUrl({ hostType: 'localhost' }),\n () => {\n // TODO: This appears to be happening consistently after an hour.\n // We should investigate why this is happening and fix it on our servers.\n // Log.error(\n // chalk.red(\n // '\\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.'\n // )\n // );\n // Log.exception(error);\n this.devSession?.closeAsync().catch((error) => {\n debug('[dev-session] error closing: ' + error.message);\n });\n }\n );\n\n await this.devSession.startAsync({\n runtime: this.isTargetingNative() ? 'native' : 'web',\n });\n }\n\n public isTargetingNative() {\n // Temporary hack while we implement multi-bundler dev server proxy.\n return true;\n }\n\n public isTargetingWeb() {\n return this.platformBundlers.web === this.name;\n }\n\n /**\n * Sends a message over web sockets to any connected device,\n * does nothing when the dev server is not running.\n *\n * @param method name of the command. In RN projects `reload`, and `devMenu` are available. In Expo Go, `sendDevCommand` is available.\n * @param params\n */\n public broadcastMessage(\n method: 'reload' | 'devMenu' | 'sendDevCommand',\n params?: Record<string, any>\n ) {\n this.getInstance()?.messageSocket.broadcast(method, params);\n }\n\n /** Get the running dev server instance. */\n public getInstance() {\n return this.instance;\n }\n\n /** Stop the running dev server instance. */\n async stopAsync() {\n // Stop the dev session timer and tell Expo API to remove dev session.\n await this.devSession?.closeAsync();\n\n // Stop ngrok if running.\n await this.ngrok?.stopAsync().catch((e) => {\n Log.error(`Error stopping ngrok:`);\n Log.exception(e);\n });\n\n return resolveWithTimeout(\n () =>\n new Promise<void>((resolve, reject) => {\n // Close the server.\n debug(`Stopping dev server (bundler: ${this.name})`);\n\n if (this.instance?.server) {\n this.instance.server.close((error) => {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n if (error) {\n reject(error);\n } else {\n resolve();\n }\n });\n } else {\n debug(`Stopped dev server (bundler: ${this.name})`);\n this.instance = null;\n resolve();\n }\n }),\n {\n // NOTE(Bacon): Metro dev server doesn't seem to be closing in time.\n timeout: 1000,\n errorMessage: `Timeout waiting for '${this.name}' dev server to close`,\n }\n );\n }\n\n protected getUrlCreator(options: Partial<Pick<BundlerStartOptions, 'port' | 'location'>> = {}) {\n if (!this.urlCreator) {\n assert(options?.port, 'Dev server instance not found');\n this.urlCreator = new UrlCreator(options.location, {\n port: options.port,\n getTunnelUrl: this.getTunnelUrl.bind(this),\n });\n }\n return this.urlCreator;\n }\n\n public getNativeRuntimeUrl(opts: Partial<CreateURLOptions> = {}) {\n return this.isDevClient\n ? this.getUrlCreator().constructDevClientUrl(opts) ?? this.getDevServerUrl()\n : this.getUrlCreator().constructUrl({ ...opts, scheme: 'exp' });\n }\n\n /** Get the URL for the running instance of the dev server. */\n public getDevServerUrl(options: { hostType?: 'localhost' } = {}): string | null {\n const instance = this.getInstance();\n if (!instance?.location) {\n return null;\n }\n const { location } = instance;\n if (options.hostType === 'localhost') {\n return `${location.protocol}://localhost:${location.port}`;\n }\n return location.url ?? null;\n }\n\n /** Get the tunnel URL from ngrok. */\n public getTunnelUrl(): string | null {\n return this.ngrok?.getActiveUrl() ?? null;\n }\n\n /** Open the dev server in a runtime. */\n public async openPlatformAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS | 'desktop',\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n if (launchTarget === 'desktop') {\n const serverUrl = this.getDevServerUrl({ hostType: 'localhost' });\n // Allow opening the tunnel URL when using Metro web.\n const url = this.name === 'metro' ? this.getTunnelUrl() ?? serverUrl : serverUrl;\n await openBrowserAsync(url!);\n return { url };\n }\n\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime }, resolver);\n }\n\n /** Open the dev server in a runtime. */\n public async openCustomRuntimeAsync(\n launchTarget: keyof typeof PLATFORM_MANAGERS,\n launchProps: Partial<BaseOpenInCustomProps> = {},\n resolver: BaseResolveDeviceProps<any> = {}\n ) {\n const runtime = this.isTargetingNative() ? (this.isDevClient ? 'custom' : 'expo') : 'web';\n if (runtime !== 'custom') {\n throw new CommandError(\n `dev server cannot open custom runtimes either because it does not target native platforms or because it is not targeting dev clients. (target: ${runtime})`\n );\n }\n\n const manager = await this.getPlatformManagerAsync(launchTarget);\n return manager.openAsync({ runtime: 'custom', props: launchProps }, resolver);\n }\n\n /** Get the URL for opening in Expo Go. */\n protected getExpoGoUrl(): string {\n return this.getUrlCreator().constructUrl({ scheme: 'exp' });\n }\n\n /** Should use the interstitial page for selecting which runtime to use. */\n protected isRedirectPageEnabled(): boolean {\n return (\n !env.EXPO_NO_REDIRECT_PAGE &&\n // if user passed --dev-client flag, skip interstitial page\n !this.isDevClient &&\n // Checks if dev client is installed.\n !!resolveFrom.silent(this.projectRoot, 'expo-dev-client')\n );\n }\n\n /** Get the redirect URL when redirecting is enabled. */\n public getRedirectUrl(platform: keyof typeof PLATFORM_MANAGERS | null = null): string | null {\n if (!this.isRedirectPageEnabled()) {\n debug('Redirect page is disabled');\n return null;\n }\n\n return (\n this.getUrlCreator().constructLoadingUrl(\n {},\n platform === 'emulator' ? 'android' : platform === 'simulator' ? 'ios' : null\n ) ?? null\n );\n }\n\n protected async getPlatformManagerAsync(platform: keyof typeof PLATFORM_MANAGERS) {\n if (!this.platformManagers[platform]) {\n const Manager = PLATFORM_MANAGERS[platform]();\n const port = this.getInstance()?.location.port;\n if (!port || !this.urlCreator) {\n throw new CommandError(\n 'DEV_SERVER',\n 'Cannot interact with native platforms until dev server has started'\n );\n }\n debug(`Creating platform manager (platform: ${platform}, port: ${port})`);\n this.platformManagers[platform] = new Manager(this.projectRoot, port, {\n getCustomRuntimeUrl: this.urlCreator.constructDevClientUrl.bind(this.urlCreator),\n getExpoGoUrl: this.getExpoGoUrl.bind(this),\n getRedirectUrl: this.getRedirectUrl.bind(this, platform),\n getDevServerUrl: this.getDevServerUrl.bind(this, { hostType: 'localhost' }),\n });\n }\n return this.platformManagers[platform];\n }\n}\n"],"names":["Log","debug","require","PLATFORM_MANAGERS","simulator","ApplePlatformManager","emulator","AndroidPlatformManager","MIDDLEWARES","classic","ClassicManifestMiddleware","ExpoGoManifestHandlerMiddleware","BundlerDevServer","constructor","projectRoot","platformBundlers","isDevClient","ngrok","devSession","instance","platformManagers","urlCreator","setInstance","getManifestMiddlewareAsync","options","manifestType","forceManifestType","assert","Middleware","getUrlCreator","middleware","constructUrl","bind","mode","minify","isNativeWebpack","name","isTargetingNative","privateKeyPath","getHandler","startAsync","stopAsync","headless","startHeadlessAsync","startImplementationAsync","postStartAsync","port","CommandError","server","close","location","host","url","protocol","messageSocket","broadcast","hostType","APISettings","isOffline","_startTunnelAsync","startDevSessionAsync","watchConfig","notifier","FileNotifier","getConfigModuleIds","startObserving","getInstance","AsyncNgrok","stopNotifying","DevelopmentSession","getNativeRuntimeUrl","getDevServerUrl","closeAsync","catch","error","message","runtime","isTargetingWeb","web","broadcastMessage","method","params","e","exception","resolveWithTimeout","Promise","resolve","reject","timeout","errorMessage","UrlCreator","getTunnelUrl","opts","constructDevClientUrl","scheme","getActiveUrl","openPlatformAsync","launchTarget","resolver","serverUrl","openBrowserAsync","manager","getPlatformManagerAsync","openAsync","openCustomRuntimeAsync","launchProps","props","getExpoGoUrl","isRedirectPageEnabled","env","EXPO_NO_REDIRECT_PAGE","resolveFrom","silent","getRedirectUrl","platform","constructLoadingUrl","Manager","getCustomRuntimeUrl"],"mappings":"AAAA;;;;AACmB,IAAA,OAAQ,kCAAR,QAAQ,EAAA;AACE,IAAA,UAAY,kCAAZ,YAAY,EAAA;AACjB,IAAA,YAAc,kCAAd,cAAc,EAAA;AAEV,IAAA,SAAoB,WAApB,oBAAoB,CAAA;AACpCA,IAAAA,GAAG,mCAAM,WAAW,EAAjB;AACc,IAAA,aAA0B,WAA1B,0BAA0B,CAAA;AACpB,IAAA,MAAmB,WAAnB,mBAAmB,CAAA;AAClC,IAAA,IAAiB,WAAjB,iBAAiB,CAAA;AACR,IAAA,OAAoB,WAApB,oBAAoB,CAAA;AAMtB,IAAA,WAAc,WAAd,cAAc,CAAA;AACN,IAAA,mBAAsB,WAAtB,sBAAsB,CAAA;AACZ,IAAA,WAAc,WAAd,cAAc,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;AAG3D,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,6BAA6B,CAAC,AAAsB,AAAC;AAqDpF,MAAMC,iBAAiB,GAAG;IACxBC,SAAS,EAAE,IACTF,OAAO,CAAC,uCAAuC,CAAC,CAC7CG,oBAAoB;IAA+E;IACxGC,QAAQ,EAAE,IACRJ,OAAO,CAAC,6CAA6C,CAAC,CACnDK,sBAAsB;CAC5B,AAAC;AAEF,MAAMC,WAAW,GAAG;IAClBC,OAAO,EAAE,IACPP,OAAO,CAAC,wCAAwC,CAAC,CAC9CQ,yBAAyB;IAAqF;IACnH,cAAc,EAAE,IACdR,OAAO,CAAC,8CAA8C,CAAC,CACpDS,+BAA+B;CACrC,AAAC;AAEK,MAAeC,gBAAgB;IAepCC,YAESC,WAAmB,EAEnBC,gBAAkC,EAElCC,WAAqB,CAC5B;aALOF,WAAmB,GAAnBA,WAAmB;aAEnBC,gBAAkC,GAAlCA,gBAAkC;aAElCC,WAAqB,GAArBA,WAAqB;aAhBpBC,KAAK,GAAsB,IAAI;aAE/BC,UAAU,GAA8B,IAAI;aAE5CC,QAAQ,GAA6B,IAAI;aAE3CC,gBAAgB,GAAyC,EAAE;aAEzDC,UAAU,GAAuB,IAAI;KAS3C;IAEJ,AAAUC,WAAW,CAACH,QAA2B,EAAE;QACjD,IAAI,CAACA,QAAQ,GAAGA,QAAQ,CAAC;KAC1B;IAED,4CAA4C,CAC5C,MAAgBI,0BAA0B,CACxCC,OAGC,GAAG,EAAE,EACN;QACA,MAAMC,YAAY,GAAGD,OAAO,CAACE,iBAAiB,IAAI,SAAS,AAAC;QAC5DC,CAAAA,GAAAA,OAAM,AAAyF,CAAA,QAAzF,CAACF,YAAY,IAAIjB,WAAW,EAAE,CAAC,8BAA8B,EAAEiB,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;QAChG,MAAMG,UAAU,GAAGpB,WAAW,CAACiB,YAAY,CAAC,EAAE,AAAC;QAE/C,MAAMJ,UAAU,GAAG,IAAI,CAACQ,aAAa,EAAE,AAAC;QACxC,MAAMC,UAAU,GAAG,IAAIF,UAAU,CAAC,IAAI,CAACd,WAAW,EAAE;YAClDiB,YAAY,EAAEV,UAAU,CAACU,YAAY,CAACC,IAAI,CAACX,UAAU,CAAC;YACtDY,IAAI,EAAET,OAAO,CAACS,IAAI;YAClBC,MAAM,EAAEV,OAAO,CAACU,MAAM;YACtBC,eAAe,EAAE,IAAI,CAACC,IAAI,KAAK,SAAS,IAAI,IAAI,CAACC,iBAAiB,EAAE;YACpEC,cAAc,EAAEd,OAAO,CAACc,cAAc;SACvC,CAAC,AAAC;QACH,OAAOR,UAAU,CAACS,UAAU,EAAE,CAAC;KAChC;IAED,wEAAwE,CACxE,MAAaC,UAAU,CAAChB,OAA4B,EAA8B;QAChF,MAAM,IAAI,CAACiB,SAAS,EAAE,CAAC;QAEvB,IAAItB,QAAQ,AAAmB,AAAC;QAChC,IAAIK,OAAO,CAACkB,QAAQ,EAAE;YACpBvB,QAAQ,GAAG,MAAM,IAAI,CAACwB,kBAAkB,CAACnB,OAAO,CAAC,CAAC;SACnD,MAAM;YACLL,QAAQ,GAAG,MAAM,IAAI,CAACyB,wBAAwB,CAACpB,OAAO,CAAC,CAAC;SACzD;QAED,IAAI,CAACF,WAAW,CAACH,QAAQ,CAAC,CAAC;QAC3B,MAAM,IAAI,CAAC0B,cAAc,CAACrB,OAAO,CAAC,CAAC;QACnC,OAAOL,QAAQ,CAAC;KACjB;IAMD;;;KAGG,CACH,MAAcwB,kBAAkB,CAACnB,OAA4B,EAA8B;QACzF,IAAI,CAACA,OAAO,CAACsB,IAAI,EACf,MAAM,IAAIC,OAAY,aAAA,CAAC,iBAAiB,EAAE,4CAA4C,CAAC,CAAC;QAC1F,IAAI,CAAC1B,UAAU,GAAG,IAAI,CAACQ,aAAa,CAACL,OAAO,CAAC,CAAC;QAE9C,OAAO;YACL,uBAAuB;YACvBwB,MAAM,EAAE;gBACNC,KAAK,EAAE,IAAM;oBACX,IAAI,CAAC9B,QAAQ,GAAG,IAAI,CAAC;iBACtB;aACF;YACD+B,QAAQ,EAAE;gBACR,mDAAmD;gBACnDJ,IAAI,EAAEtB,OAAO,CAACsB,IAAI;gBAClB,kCAAkC;gBAClCK,IAAI,EAAE,WAAW;gBACjB,iDAAiD;gBACjDC,GAAG,EAAE,CAAC,iBAAiB,EAAE5B,OAAO,CAACsB,IAAI,CAAC,CAAC;gBACvCO,QAAQ,EAAE,MAAM;aACjB;YACDvB,UAAU,EAAE,EAAE;YACdwB,aAAa,EAAE;gBACbC,SAAS,EAAE,IAAM;oBACf,MAAM,IAAIR,OAAY,aAAA,CAAC,iBAAiB,EAAE,8CAA8C,CAAC,CAAC;iBAC3F;aACF;SACF,CAAC;KACH;IAED;;;KAGG,CACH,MAAgBF,cAAc,CAACrB,OAA4B,EAAE;QAC3D,IACEA,OAAO,CAAC0B,QAAQ,CAACM,QAAQ,KAAK,QAAQ,IACtC,CAACC,SAAW,YAAA,CAACC,SAAS,IACtB,4FAA4F;QAC5F,IAAI,CAACrB,iBAAiB,EAAE,EACxB;YACA,MAAM,IAAI,CAACsB,iBAAiB,EAAE,CAAC;SAChC;QACD,MAAM,IAAI,CAACC,oBAAoB,EAAE,CAAC;QAElC,IAAI,CAACC,WAAW,EAAE,CAAC;KACpB;IAID,AAAUA,WAAW,GAAG;QACtB,MAAMC,QAAQ,GAAG,IAAIC,aAAY,aAAA,CAAC,IAAI,CAACjD,WAAW,EAAE,IAAI,CAACkD,kBAAkB,EAAE,CAAC,AAAC;QAC/EF,QAAQ,CAACG,cAAc,EAAE,CAAC;KAC3B;IAED,8EAA8E,CAC9E,MAAaN,iBAAiB,GAA+B;YAC9C,GAAkB;QAA/B,MAAMb,IAAI,GAAG,CAAA,GAAkB,GAAlB,IAAI,CAACoB,WAAW,EAAE,SAAU,GAA5B,KAAA,CAA4B,GAA5B,GAAkB,CAAEhB,QAAQ,CAACJ,IAAI,AAAC;QAC/C,IAAI,CAACA,IAAI,EAAE,OAAO,IAAI,CAAC;QACvB7C,KAAK,CAAC,2BAA2B,GAAG6C,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC7B,KAAK,GAAG,IAAIkD,WAAU,WAAA,CAAC,IAAI,CAACrD,WAAW,EAAEgC,IAAI,CAAC,CAAC;QACpD,MAAM,IAAI,CAAC7B,KAAK,CAACuB,UAAU,EAAE,CAAC;QAC9B,OAAO,IAAI,CAACvB,KAAK,CAAC;KACnB;IAED,MAAgB2C,oBAAoB,GAAG;QACrC,uFAAuF;QACvF,oDAAoD;QAEpD,IAAI,IAAI,CAAC1C,UAAU,EAAE;YACnB,IAAI,CAACA,UAAU,CAACkD,aAAa,EAAE,CAAC;SACjC;QAED,IAAI,CAAClD,UAAU,GAAG,IAAImD,mBAAkB,mBAAA,CACtC,IAAI,CAACvD,WAAW,EAChB,kFAAkF;QAClF,IAAI,CAACuB,iBAAiB,EAAE,GACpB,IAAI,CAACiC,mBAAmB,EAAE,GAC1B,IAAI,CAACC,eAAe,CAAC;YAAEf,QAAQ,EAAE,WAAW;SAAE,CAAC,EACnD,IAAM;gBACJ,iEAAiE;YACjE,yEAAyE;YACzE,aAAa;YACb,eAAe;YACf,uMAAuM;YACvM,MAAM;YACN,KAAK;YACL,wBAAwB;YACxB,GAAe;YAAf,CAAA,GAAe,GAAf,IAAI,CAACtC,UAAU,SAAY,GAA3B,KAAA,CAA2B,GAA3B,GAAe,CAAEsD,UAAU,EAAE,CAACC,KAAK,CAAC,CAACC,KAAK,GAAK;gBAC7CzE,KAAK,CAAC,+BAA+B,GAAGyE,KAAK,CAACC,OAAO,CAAC,CAAC;aACxD,CAAC,CAAC;SACJ,CACF,CAAC;QAEF,MAAM,IAAI,CAACzD,UAAU,CAACsB,UAAU,CAAC;YAC/BoC,OAAO,EAAE,IAAI,CAACvC,iBAAiB,EAAE,GAAG,QAAQ,GAAG,KAAK;SACrD,CAAC,CAAC;KACJ;IAED,AAAOA,iBAAiB,GAAG;QACzB,oEAAoE;QACpE,OAAO,IAAI,CAAC;KACb;IAED,AAAOwC,cAAc,GAAG;QACtB,OAAO,IAAI,CAAC9D,gBAAgB,CAAC+D,GAAG,KAAK,IAAI,CAAC1C,IAAI,CAAC;KAChD;IAED;;;;;;KAMG,CACH,AAAO2C,gBAAgB,CACrBC,MAA+C,EAC/CC,MAA4B,EAC5B;YACA,GAAkB;QAAlB,CAAA,GAAkB,GAAlB,IAAI,CAACf,WAAW,EAAE,SAAe,GAAjC,KAAA,CAAiC,GAAjC,GAAkB,CAAEZ,aAAa,CAACC,SAAS,CAACyB,MAAM,EAAEC,MAAM,CAAC,CAAC;KAC7D;IAED,2CAA2C,CAC3C,AAAOf,WAAW,GAAG;QACnB,OAAO,IAAI,CAAC/C,QAAQ,CAAC;KACtB;IAED,4CAA4C,CAC5C,MAAMsB,SAAS,GAAG;YAEV,IAAe,EAGf,IAAU;QAJhB,sEAAsE;QACtE,OAAM,CAAA,IAAe,GAAf,IAAI,CAACvB,UAAU,SAAY,GAA3B,KAAA,CAA2B,GAA3B,IAAe,CAAEsD,UAAU,EAAE,CAAA,CAAC;QAEpC,yBAAyB;QACzB,MAAM,CAAA,CAAA,IAAU,GAAV,IAAI,CAACvD,KAAK,SAAW,GAArB,KAAA,CAAqB,GAArB,IAAU,CAAEwB,SAAS,EAAE,CAACgC,KAAK,CAAC,CAACS,CAAC,GAAK;YACzClF,GAAG,CAAC0E,KAAK,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC;YACnC1E,GAAG,CAACmF,SAAS,CAACD,CAAC,CAAC,CAAC;SAClB,CAAC,CAAA,CAAC;QAEH,OAAOE,CAAAA,GAAAA,MAAkB,AA2BxB,CAAA,mBA3BwB,CACvB;YACE,OAAA,IAAIC,OAAO,CAAO,CAACC,OAAO,EAAEC,MAAM,GAAK;oBAIjC,GAAa;gBAHjB,oBAAoB;gBACpBtF,KAAK,CAAC,CAAC,8BAA8B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;gBAErD,IAAI,CAAA,GAAa,GAAb,IAAI,CAACjB,QAAQ,SAAQ,GAArB,KAAA,CAAqB,GAArB,GAAa,CAAE6B,MAAM,EAAE;oBACzB,IAAI,CAAC7B,QAAQ,CAAC6B,MAAM,CAACC,KAAK,CAAC,CAACyB,KAAK,GAAK;wBACpCzE,KAAK,CAAC,CAAC,6BAA6B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;wBACpD,IAAI,CAACjB,QAAQ,GAAG,IAAI,CAAC;wBACrB,IAAIuD,KAAK,EAAE;4BACTa,MAAM,CAACb,KAAK,CAAC,CAAC;yBACf,MAAM;4BACLY,OAAO,EAAE,CAAC;yBACX;qBACF,CAAC,CAAC;iBACJ,MAAM;oBACLrF,KAAK,CAAC,CAAC,6BAA6B,EAAE,IAAI,CAACmC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpD,IAAI,CAACjB,QAAQ,GAAG,IAAI,CAAC;oBACrBmE,OAAO,EAAE,CAAC;iBACX;aACF,CAAC,CAAA;SAAA,EACJ;YACE,oEAAoE;YACpEE,OAAO,EAAE,IAAI;YACbC,YAAY,EAAE,CAAC,qBAAqB,EAAE,IAAI,CAACrD,IAAI,CAAC,qBAAqB,CAAC;SACvE,CACF,CAAC;KACH;IAED,AAAUP,aAAa,CAACL,OAAgE,GAAG,EAAE,EAAE;QAC7F,IAAI,CAAC,IAAI,CAACH,UAAU,EAAE;YACpBM,CAAAA,GAAAA,OAAM,AAAgD,CAAA,QAAhD,CAACH,OAAO,QAAM,GAAbA,KAAAA,CAAa,GAAbA,OAAO,CAAEsB,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACvD,IAAI,CAACzB,UAAU,GAAG,IAAIqE,WAAU,WAAA,CAAClE,OAAO,CAAC0B,QAAQ,EAAE;gBACjDJ,IAAI,EAAEtB,OAAO,CAACsB,IAAI;gBAClB6C,YAAY,EAAE,IAAI,CAACA,YAAY,CAAC3D,IAAI,CAAC,IAAI,CAAC;aAC3C,CAAC,CAAC;SACJ;QACD,OAAO,IAAI,CAACX,UAAU,CAAC;KACxB;IAED,AAAOiD,mBAAmB,CAACsB,IAA+B,GAAG,EAAE,EAAE;YAE3D,GAAgD;QADpD,OAAO,IAAI,CAAC5E,WAAW,GACnB,CAAA,GAAgD,GAAhD,IAAI,CAACa,aAAa,EAAE,CAACgE,qBAAqB,CAACD,IAAI,CAAC,YAAhD,GAAgD,GAAI,IAAI,CAACrB,eAAe,EAAE,GAC1E,IAAI,CAAC1C,aAAa,EAAE,CAACE,YAAY,CAAC;YAAE,GAAG6D,IAAI;YAAEE,MAAM,EAAE,KAAK;SAAE,CAAC,CAAC;KACnE;IAED,8DAA8D,CAC9D,AAAOvB,eAAe,CAAC/C,OAAmC,GAAG,EAAE,EAAiB;QAC9E,MAAML,QAAQ,GAAG,IAAI,CAAC+C,WAAW,EAAE,AAAC;QACpC,IAAI,CAAC/C,CAAAA,QAAQ,QAAU,GAAlBA,KAAAA,CAAkB,GAAlBA,QAAQ,CAAE+B,QAAQ,CAAA,EAAE;YACvB,OAAO,IAAI,CAAC;SACb;QACD,MAAM,EAAEA,QAAQ,CAAA,EAAE,GAAG/B,QAAQ,AAAC;QAC9B,IAAIK,OAAO,CAACgC,QAAQ,KAAK,WAAW,EAAE;YACpC,OAAO,CAAC,EAAEN,QAAQ,CAACG,QAAQ,CAAC,aAAa,EAAEH,QAAQ,CAACJ,IAAI,CAAC,CAAC,CAAC;SAC5D;YACMI,IAAY;QAAnB,OAAOA,CAAAA,IAAY,GAAZA,QAAQ,CAACE,GAAG,YAAZF,IAAY,GAAI,IAAI,CAAC;KAC7B;IAED,qCAAqC,CACrC,AAAOyC,YAAY,GAAkB;YAC5B,GAAU;YAAV,IAA0B;QAAjC,OAAO,CAAA,IAA0B,GAA1B,CAAA,GAAU,GAAV,IAAI,CAAC1E,KAAK,SAAc,GAAxB,KAAA,CAAwB,GAAxB,GAAU,CAAE8E,YAAY,EAAE,YAA1B,IAA0B,GAAI,IAAI,CAAC;KAC3C;IAED,wCAAwC,CACxC,MAAaC,iBAAiB,CAC5BC,YAAwD,EACxDC,QAAqC,GAAG,EAAE,EAC1C;QACA,IAAID,YAAY,KAAK,SAAS,EAAE;YAC9B,MAAME,SAAS,GAAG,IAAI,CAAC5B,eAAe,CAAC;gBAAEf,QAAQ,EAAE,WAAW;aAAE,CAAC,AAAC;gBAE9B,GAAmB;YADvD,qDAAqD;YACrD,MAAMJ,GAAG,GAAG,IAAI,CAAChB,IAAI,KAAK,OAAO,GAAG,CAAA,GAAmB,GAAnB,IAAI,CAACuD,YAAY,EAAE,YAAnB,GAAmB,GAAIQ,SAAS,GAAGA,SAAS,AAAC;YACjF,MAAMC,CAAAA,GAAAA,UAAgB,AAAM,CAAA,QAAN,CAAChD,GAAG,CAAE,CAAC;YAC7B,OAAO;gBAAEA,GAAG;aAAE,CAAC;SAChB;QAED,MAAMwB,OAAO,GAAG,IAAI,CAACvC,iBAAiB,EAAE,GAAI,IAAI,CAACrB,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAI,KAAK,AAAC;QAC1F,MAAMqF,OAAO,GAAG,MAAM,IAAI,CAACC,uBAAuB,CAACL,YAAY,CAAC,AAAC;QACjE,OAAOI,OAAO,CAACE,SAAS,CAAC;YAAE3B,OAAO;SAAE,EAAEsB,QAAQ,CAAC,CAAC;KACjD;IAED,wCAAwC,CACxC,MAAaM,sBAAsB,CACjCP,YAA4C,EAC5CQ,WAA2C,GAAG,EAAE,EAChDP,QAAqC,GAAG,EAAE,EAC1C;QACA,MAAMtB,OAAO,GAAG,IAAI,CAACvC,iBAAiB,EAAE,GAAI,IAAI,CAACrB,WAAW,GAAG,QAAQ,GAAG,MAAM,GAAI,KAAK,AAAC;QAC1F,IAAI4D,OAAO,KAAK,QAAQ,EAAE;YACxB,MAAM,IAAI7B,OAAY,aAAA,CACpB,CAAC,+IAA+I,EAAE6B,OAAO,CAAC,CAAC,CAAC,CAC7J,CAAC;SACH;QAED,MAAMyB,OAAO,GAAG,MAAM,IAAI,CAACC,uBAAuB,CAACL,YAAY,CAAC,AAAC;QACjE,OAAOI,OAAO,CAACE,SAAS,CAAC;YAAE3B,OAAO,EAAE,QAAQ;YAAE8B,KAAK,EAAED,WAAW;SAAE,EAAEP,QAAQ,CAAC,CAAC;KAC/E;IAED,0CAA0C,CAC1C,AAAUS,YAAY,GAAW;QAC/B,OAAO,IAAI,CAAC9E,aAAa,EAAE,CAACE,YAAY,CAAC;YAAE+D,MAAM,EAAE,KAAK;SAAE,CAAC,CAAC;KAC7D;IAED,2EAA2E,CAC3E,AAAUc,qBAAqB,GAAY;QACzC,OACE,CAACC,IAAG,IAAA,CAACC,qBAAqB,IAC1B,2DAA2D;QAC3D,CAAC,IAAI,CAAC9F,WAAW,IACjB,qCAAqC;QACrC,CAAC,CAAC+F,YAAW,QAAA,CAACC,MAAM,CAAC,IAAI,CAAClG,WAAW,EAAE,iBAAiB,CAAC,CACzD;KACH;IAED,wDAAwD,CACxD,AAAOmG,cAAc,CAACC,QAA+C,GAAG,IAAI,EAAiB;QAC3F,IAAI,CAAC,IAAI,CAACN,qBAAqB,EAAE,EAAE;YACjC3G,KAAK,CAAC,2BAA2B,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC;SACb;YAGC,GAGC;QAJH,OACE,CAAA,GAGC,GAHD,IAAI,CAAC4B,aAAa,EAAE,CAACsF,mBAAmB,CACtC,EAAE,EACFD,QAAQ,KAAK,UAAU,GAAG,SAAS,GAAGA,QAAQ,KAAK,WAAW,GAAG,KAAK,GAAG,IAAI,CAC9E,YAHD,GAGC,GAAI,IAAI,CACT;KACH;IAED,MAAgBZ,uBAAuB,CAACY,QAAwC,EAAE;QAChF,IAAI,CAAC,IAAI,CAAC9F,gBAAgB,CAAC8F,QAAQ,CAAC,EAAE;gBAEvB,GAAkB;YAD/B,MAAME,OAAO,GAAGjH,iBAAiB,CAAC+G,QAAQ,CAAC,EAAE,AAAC;YAC9C,MAAMpE,IAAI,GAAG,CAAA,GAAkB,GAAlB,IAAI,CAACoB,WAAW,EAAE,SAAU,GAA5B,KAAA,CAA4B,GAA5B,GAAkB,CAAEhB,QAAQ,CAACJ,IAAI,AAAC;YAC/C,IAAI,CAACA,IAAI,IAAI,CAAC,IAAI,CAACzB,UAAU,EAAE;gBAC7B,MAAM,IAAI0B,OAAY,aAAA,CACpB,YAAY,EACZ,oEAAoE,CACrE,CAAC;aACH;YACD9C,KAAK,CAAC,CAAC,qCAAqC,EAAEiH,QAAQ,CAAC,QAAQ,EAAEpE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,IAAI,CAAC1B,gBAAgB,CAAC8F,QAAQ,CAAC,GAAG,IAAIE,OAAO,CAAC,IAAI,CAACtG,WAAW,EAAEgC,IAAI,EAAE;gBACpEuE,mBAAmB,EAAE,IAAI,CAAChG,UAAU,CAACwE,qBAAqB,CAAC7D,IAAI,CAAC,IAAI,CAACX,UAAU,CAAC;gBAChFsF,YAAY,EAAE,IAAI,CAACA,YAAY,CAAC3E,IAAI,CAAC,IAAI,CAAC;gBAC1CiF,cAAc,EAAE,IAAI,CAACA,cAAc,CAACjF,IAAI,CAAC,IAAI,EAAEkF,QAAQ,CAAC;gBACxD3C,eAAe,EAAE,IAAI,CAACA,eAAe,CAACvC,IAAI,CAAC,IAAI,EAAE;oBAAEwB,QAAQ,EAAE,WAAW;iBAAE,CAAC;aAC5E,CAAC,CAAC;SACJ;QACD,OAAO,IAAI,CAACpC,gBAAgB,CAAC8F,QAAQ,CAAC,CAAC;KACxC;CACF;QA3WqBtG,gBAAgB,GAAhBA,gBAAgB"}
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", {
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
|
+
exports.getDeepLinkHandler = getDeepLinkHandler;
|
|
6
|
+
var _config = require("@expo/config");
|
|
5
7
|
var _devServer = require("@expo/dev-server");
|
|
8
|
+
var _getDevClientProperties = _interopRequireDefault(require("../../../utils/analytics/getDevClientProperties"));
|
|
9
|
+
var _rudderstackClient = require("../../../utils/analytics/rudderstackClient");
|
|
6
10
|
var _port = require("../../../utils/port");
|
|
7
11
|
var _bundlerDevServer = require("../BundlerDevServer");
|
|
8
12
|
var _createFileMiddleware = require("../middleware/CreateFileMiddleware");
|
|
@@ -11,6 +15,11 @@ var _interstitialPageMiddleware = require("../middleware/InterstitialPageMiddlew
|
|
|
11
15
|
var _runtimeRedirectMiddleware = require("../middleware/RuntimeRedirectMiddleware");
|
|
12
16
|
var _serveStaticMiddleware = require("../middleware/ServeStaticMiddleware");
|
|
13
17
|
var _instantiateMetro = require("./instantiateMetro");
|
|
18
|
+
function _interopRequireDefault(obj) {
|
|
19
|
+
return obj && obj.__esModule ? obj : {
|
|
20
|
+
default: obj
|
|
21
|
+
};
|
|
22
|
+
}
|
|
14
23
|
/** Default port to use for apps running in Expo Go. */ const EXPO_GO_METRO_PORT = 19000;
|
|
15
24
|
/** Default port to use for apps that run in standard React Native projects or Expo Dev Clients. */ const DEV_CLIENT_METRO_PORT = 8081;
|
|
16
25
|
class MetroBundlerDevServer extends _bundlerDevServer.BundlerDevServer {
|
|
@@ -50,11 +59,7 @@ class MetroBundlerDevServer extends _bundlerDevServer.BundlerDevServer {
|
|
|
50
59
|
scheme: (_scheme = options.location.scheme) != null ? _scheme : null
|
|
51
60
|
}).getHandler());
|
|
52
61
|
const deepLinkMiddleware = new _runtimeRedirectMiddleware.RuntimeRedirectMiddleware(this.projectRoot, {
|
|
53
|
-
onDeepLink: (
|
|
54
|
-
// eslint-disable-next-line no-useless-return
|
|
55
|
-
if (runtime === "expo") return;
|
|
56
|
-
// TODO: Some heavy analytics...
|
|
57
|
-
},
|
|
62
|
+
onDeepLink: getDeepLinkHandler(this.projectRoot),
|
|
58
63
|
getLocation: ({ runtime })=>{
|
|
59
64
|
if (runtime === "custom") {
|
|
60
65
|
var ref;
|
|
@@ -108,5 +113,15 @@ class MetroBundlerDevServer extends _bundlerDevServer.BundlerDevServer {
|
|
|
108
113
|
}
|
|
109
114
|
}
|
|
110
115
|
exports.MetroBundlerDevServer = MetroBundlerDevServer;
|
|
116
|
+
function getDeepLinkHandler(projectRoot) {
|
|
117
|
+
return async ({ runtime })=>{
|
|
118
|
+
if (runtime === "expo") return;
|
|
119
|
+
const { exp } = (0, _config).getConfig(projectRoot);
|
|
120
|
+
await (0, _rudderstackClient).logEventAsync("dev client start command", {
|
|
121
|
+
status: "started",
|
|
122
|
+
...(0, _getDevClientProperties).default(projectRoot, exp)
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
}
|
|
111
126
|
|
|
112
127
|
//# sourceMappingURL=MetroBundlerDevServer.js.map
|