@expo/cli 54.0.24 → 54.0.25

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.
Files changed (56) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/api/rest/client.js +27 -12
  3. package/build/src/api/rest/client.js.map +1 -1
  4. package/build/src/api/user/UserSettings.js +4 -2
  5. package/build/src/api/user/UserSettings.js.map +1 -1
  6. package/build/src/export/embed/exportEmbedAsync.js +3 -3
  7. package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
  8. package/build/src/export/embed/exportServer.js +1 -1
  9. package/build/src/export/embed/exportServer.js.map +1 -1
  10. package/build/src/export/exportApp.js +1 -1
  11. package/build/src/export/exportApp.js.map +1 -1
  12. package/build/src/export/publicFolder.js +19 -1
  13. package/build/src/export/publicFolder.js.map +1 -1
  14. package/build/src/prebuild/resolveTemplate.js +10 -5
  15. package/build/src/prebuild/resolveTemplate.js.map +1 -1
  16. package/build/src/run/android/resolveLaunchProps.js +4 -1
  17. package/build/src/run/android/resolveLaunchProps.js.map +1 -1
  18. package/build/src/run/ios/appleDevice/client/LockdowndClient.js +1 -1
  19. package/build/src/run/ios/appleDevice/client/LockdowndClient.js.map +1 -1
  20. package/build/src/start/platforms/android/adb.js +16 -15
  21. package/build/src/start/platforms/android/adb.js.map +1 -1
  22. package/build/src/start/server/DevToolsPluginManager.js.map +1 -1
  23. package/build/src/start/server/getStaticRenderFunctions.js +2 -1
  24. package/build/src/start/server/getStaticRenderFunctions.js.map +1 -1
  25. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +6 -5
  26. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  27. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js +17 -1
  28. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js.map +1 -1
  29. package/build/src/start/server/metro/dev-server/createMessageSocket.js +13 -2
  30. package/build/src/start/server/metro/dev-server/createMessageSocket.js.map +1 -1
  31. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js +10 -3
  32. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js.map +1 -1
  33. package/build/src/start/server/metro/instantiateMetro.js +7 -3
  34. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  35. package/build/src/start/server/metro/metroErrorInterface.js +5 -2
  36. package/build/src/start/server/metro/metroErrorInterface.js.map +1 -1
  37. package/build/src/start/server/metro/router.js +10 -1
  38. package/build/src/start/server/metro/router.js.map +1 -1
  39. package/build/src/start/server/middleware/InterstitialPageMiddleware.js +7 -4
  40. package/build/src/start/server/middleware/InterstitialPageMiddleware.js.map +1 -1
  41. package/build/src/start/server/middleware/ServeStaticMiddleware.js +2 -9
  42. package/build/src/start/server/middleware/ServeStaticMiddleware.js.map +1 -1
  43. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js +14 -24
  44. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js.map +1 -1
  45. package/build/src/start/server/webTemplate.js +3 -5
  46. package/build/src/start/server/webTemplate.js.map +1 -1
  47. package/build/src/utils/codesigning.js +6 -0
  48. package/build/src/utils/codesigning.js.map +1 -1
  49. package/build/src/utils/net.js +13 -0
  50. package/build/src/utils/net.js.map +1 -1
  51. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  52. package/build/src/utils/telemetry/utils/context.js +1 -1
  53. package/build/src/utils/url.js +0 -12
  54. package/build/src/utils/url.js.map +1 -1
  55. package/package.json +6 -6
  56. package/static/loading-page/index.html +10 -2
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/export/exportApp.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport type { Platform } from '@expo/config';\nimport { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { type PlatformMetadata, createMetadataJson } from './createMetadataJson';\nimport { exportAssetsAsync } from './exportAssets';\nimport {\n addDomBundleToMetadataAsync,\n exportDomComponentAsync,\n transformNativeBundleForMd5Filename,\n transformDomEntryForMd5Filename,\n} from './exportDomComponents';\nimport { assertEngineMismatchAsync, isEnableHermesManaged } from './exportHermes';\nimport {\n exportApiRoutesStandaloneAsync,\n exportFromServerAsync,\n injectScriptTags,\n} from './exportStaticAsync';\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { getPublicExpoManifestAsync } from './getPublicExpoManifest';\nimport { copyPublicFolderAsync } from './publicFolder';\nimport { Options } from './resolveOptions';\nimport {\n ExportAssetMap,\n BundleOutput,\n getFilesFromSerialAssets,\n persistMetroFilesAsync,\n BundleAssetWithFileHashes,\n} from './saveAssets';\nimport { createAssetMap } from './writeContents';\nimport * as Log from '../log';\nimport { WebSupportProjectPrerequisite } from '../start/doctor/web/WebSupportProjectPrerequisite';\nimport { DevServerManager } from '../start/server/DevServerManager';\nimport { MetroBundlerDevServer } from '../start/server/metro/MetroBundlerDevServer';\nimport { getRouterDirectoryModuleIdWithManifest } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { getEntryWithServerRoot } from '../start/server/middleware/ManifestMiddleware';\nimport { getBaseUrlFromExpoConfig } from '../start/server/middleware/metroOptions';\nimport { createTemplateHtmlFromExpoConfigAsync } from '../start/server/webTemplate';\nimport { env } from '../utils/env';\nimport { CommandError } from '../utils/errors';\nimport { setNodeEnv } from '../utils/nodeEnv';\n\nexport async function exportAppAsync(\n projectRoot: string,\n {\n platforms,\n outputDir,\n clear,\n dev,\n dumpAssetmap,\n sourceMaps,\n minify,\n bytecode,\n maxWorkers,\n skipSSG,\n hostedNative,\n }: Pick<\n Options,\n | 'dumpAssetmap'\n | 'sourceMaps'\n | 'dev'\n | 'clear'\n | 'outputDir'\n | 'platforms'\n | 'minify'\n | 'bytecode'\n | 'maxWorkers'\n | 'skipSSG'\n | 'hostedNative'\n >\n): Promise<void> {\n // Force the environment during export and do not allow overriding it.\n const environment = dev ? 'development' : 'production';\n process.env.NODE_ENV = environment;\n setNodeEnv(environment);\n\n require('@expo/env').load(projectRoot);\n\n const projectConfig = getConfig(projectRoot);\n const exp = await getPublicExpoManifestAsync(projectRoot, {\n // Web doesn't require validation.\n skipValidation: platforms.length === 1 && platforms[0] === 'web',\n });\n\n if (platforms.includes('web')) {\n await new WebSupportProjectPrerequisite(projectRoot).assertAsync();\n }\n\n const useServerRendering = ['static', 'server'].includes(exp.web?.output ?? '');\n\n if (skipSSG && exp.web?.output !== 'server') {\n throw new CommandError('--no-ssg can only be used with `web.output: server`');\n }\n\n const baseUrl = getBaseUrlFromExpoConfig(exp);\n\n if (!bytecode && (platforms.includes('ios') || platforms.includes('android'))) {\n Log.warn(\n `Bytecode makes the app startup faster, disabling bytecode is highly discouraged and should only be used for debugging purposes.`\n );\n }\n\n // Print out logs\n if (baseUrl) {\n Log.log();\n Log.log(chalk.gray`Using (experimental) base path: ${baseUrl}`);\n // Warn if not using an absolute path.\n if (!baseUrl.startsWith('/')) {\n Log.log(\n chalk.yellow` Base path does not start with a slash. Requests will not be absolute.`\n );\n }\n }\n\n const mode = dev ? 'development' : 'production';\n const publicPath = path.resolve(projectRoot, env.EXPO_PUBLIC_FOLDER);\n const outputPath = path.resolve(projectRoot, outputDir);\n\n // Write the JS bundles to disk, and get the bundle file names (this could change with async chunk loading support).\n\n const files: ExportAssetMap = new Map();\n\n const devServerManager = await DevServerManager.startMetroAsync(projectRoot, {\n minify,\n mode,\n port: 8081,\n isExporting: true,\n location: {},\n resetDevServer: clear,\n maxWorkers,\n });\n\n const devServer = devServerManager.getDefaultDevServer();\n assert(devServer instanceof MetroBundlerDevServer);\n\n const bundles: Partial<Record<Platform, BundleOutput>> = {};\n const domComponentAssetsMetadata: Partial<Record<Platform, PlatformMetadata['assets']>> = {};\n\n const spaPlatforms =\n // TODO: Support server and static rendering for server component exports.\n useServerRendering && !devServer.isReactServerComponentsEnabled\n ? platforms.filter((platform) => platform !== 'web')\n : platforms;\n\n try {\n if (devServer.isReactServerComponentsEnabled) {\n // In RSC mode, we only need these to be in the client dir.\n // TODO: Merge back with other copy after we add SSR.\n try {\n await copyPublicFolderAsync(publicPath, path.join(outputPath, 'client'));\n } catch (error) {\n Log.error('Failed to copy public directory to dist directory');\n throw error;\n }\n } else {\n // NOTE(kitten): The public folder is currently always copied, regardless of targetDomain\n // split. Hence, there's another separate `copyPublicFolderAsync` call below for `web`\n await copyPublicFolderAsync(publicPath, outputPath);\n }\n\n let templateHtml: string | undefined;\n // Can be empty during web-only SSG.\n if (spaPlatforms.length) {\n await Promise.all(\n spaPlatforms.map(async (platform) => {\n // Assert early so the user doesn't have to wait until bundling is complete to find out that\n // Hermes won't be available.\n const isHermes = isEnableHermesManaged(exp, platform);\n if (isHermes) {\n await assertEngineMismatchAsync(projectRoot, exp, platform);\n }\n\n let bundle: {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n files?: ExportAssetMap;\n };\n\n try {\n // Run metro bundler and create the JS bundles/source maps.\n bundle = await devServer.nativeExportBundleAsync(\n exp,\n {\n platform,\n splitChunks:\n !env.EXPO_NO_BUNDLE_SPLITTING &&\n ((devServer.isReactServerComponentsEnabled && !bytecode) || platform === 'web'),\n mainModuleName: getEntryWithServerRoot(projectRoot, {\n platform,\n pkg: projectConfig.pkg,\n }),\n mode: dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n serializerIncludeMaps: sourceMaps,\n bytecode: bytecode && isHermes,\n reactCompiler: !!exp.experiments?.reactCompiler,\n hosted: hostedNative,\n },\n files\n );\n } catch (error) {\n Log.log('');\n if (error instanceof Error) {\n Log.exception(error);\n } else {\n Log.error('Failed to bundle the app');\n Log.log(error as any);\n }\n process.exit(1);\n }\n\n bundles[platform] = bundle;\n\n getFilesFromSerialAssets(bundle.artifacts, {\n includeSourceMaps: sourceMaps,\n files,\n isServerHosted: devServer.isReactServerComponentsEnabled || hostedNative,\n });\n\n // TODO: Remove duplicates...\n const expoDomComponentReferences = bundle.artifacts\n .map((artifact) =>\n Array.isArray(artifact.metadata.expoDomComponentReferences)\n ? artifact.metadata.expoDomComponentReferences\n : []\n )\n .flat();\n await Promise.all(\n // TODO: Make a version of this which uses `this.metro.getBundler().buildGraphForEntries([])` to bundle all the DOM components at once.\n expoDomComponentReferences.map(async (filePath) => {\n const { bundle: platformDomComponentsBundle, htmlOutputName } =\n await exportDomComponentAsync({\n filePath,\n projectRoot,\n dev,\n devServer,\n isHermes,\n includeSourceMaps: sourceMaps,\n exp,\n files,\n useMd5Filename: true,\n });\n\n // Merge the assets from the DOM component into the output assets.\n // @ts-expect-error: mutate assets\n bundle.assets.push(...platformDomComponentsBundle.assets);\n\n transformNativeBundleForMd5Filename({\n domComponentReference: filePath,\n nativeBundle: bundle,\n files,\n htmlOutputName,\n });\n domComponentAssetsMetadata[platform] = [\n ...(domComponentAssetsMetadata[platform] || []),\n ...(await addDomBundleToMetadataAsync(platformDomComponentsBundle)),\n ...transformDomEntryForMd5Filename({\n files,\n htmlOutputName,\n }),\n ];\n })\n );\n\n if (platform === 'web') {\n // TODO: Unify with exportStaticAsync\n // TODO: Maybe move to the serializer.\n let html = await serializeHtmlWithAssets({\n isExporting: true,\n resources: bundle.artifacts,\n template: await createTemplateHtmlFromExpoConfigAsync(projectRoot, {\n scripts: [],\n cssLinks: [],\n exp: projectConfig.exp,\n }),\n baseUrl,\n });\n\n // Add the favicon assets to the HTML.\n const modifyHtml = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp: projectConfig.exp,\n });\n if (modifyHtml) {\n html = modifyHtml(html);\n }\n\n // HACK: This is used for adding SSR shims in React Server Components.\n templateHtml = html;\n\n // Generate SPA-styled HTML file.\n // If web exists, then write the template HTML file.\n files.set('index.html', {\n contents: html,\n targetDomain: devServer.isReactServerComponentsEnabled ? 'server' : 'client',\n });\n }\n })\n );\n\n if (devServer.isReactServerComponentsEnabled) {\n const isWeb = platforms.includes('web');\n\n await exportApiRoutesStandaloneAsync(devServer, {\n files,\n platform: 'web',\n apiRoutesOnly: !isWeb,\n templateHtml,\n });\n }\n\n // TODO: Use same asset system across platforms again.\n const { assets, embeddedHashSet } = await exportAssetsAsync(projectRoot, {\n files,\n exp,\n outputDir: outputPath,\n bundles,\n baseUrl,\n hostedNative,\n });\n\n if (dumpAssetmap) {\n Log.log('Creating asset map');\n files.set('assetmap.json', { contents: JSON.stringify(createAssetMap({ assets })) });\n }\n\n const targetDomain = devServer.isReactServerComponentsEnabled ? 'client/' : '';\n const fileNames = Object.fromEntries(\n Object.entries(bundles).map(([platform, bundle]) => [\n platform,\n bundle.artifacts\n .filter((asset) => asset.type === 'js')\n .map((asset) => targetDomain + asset.filename),\n ])\n );\n\n // Generate a `metadata.json` for EAS Update.\n const contents = createMetadataJson({\n bundles,\n fileNames,\n embeddedHashSet,\n domComponentAssetsMetadata,\n });\n files.set('metadata.json', { contents: JSON.stringify(contents) });\n }\n\n // Additional web-only steps...\n\n if (platforms.includes('web') && useServerRendering) {\n const exportServer = exp.web?.output === 'server';\n\n if (exportServer) {\n // TODO: Remove when this is abstracted into the files map\n await copyPublicFolderAsync(publicPath, path.resolve(outputPath, 'client'));\n }\n\n if (skipSSG) {\n Log.log('Skipping static site generation');\n await exportApiRoutesStandaloneAsync(devServer, {\n files,\n platform: 'web',\n apiRoutesOnly: true,\n });\n\n // Output a placeholder index.html if one doesn't exist in the public directory.\n // This ensures native + API routes have some content at the root URL.\n const placeholderIndex = path.resolve(outputPath, 'client/index.html');\n if (!fs.existsSync(placeholderIndex)) {\n files.set('index.html', {\n contents: `<html><body></body></html>`,\n targetDomain: 'client',\n });\n }\n } else if (\n // TODO: Support static export with RSC.\n !devServer.isReactServerComponentsEnabled\n ) {\n await exportFromServerAsync(projectRoot, devServer, {\n mode,\n files,\n clear: !!clear,\n outputDir: outputPath,\n minify,\n baseUrl,\n includeSourceMaps: sourceMaps,\n routerRoot: getRouterDirectoryModuleIdWithManifest(projectRoot, exp),\n reactCompiler: !!exp.experiments?.reactCompiler,\n exportServer,\n maxWorkers,\n isExporting: true,\n exp: projectConfig.exp,\n });\n }\n }\n } finally {\n await devServerManager.stopAsync();\n }\n\n // Write all files at the end for unified logging.\n await persistMetroFilesAsync(files, outputPath);\n}\n"],"names":["exportAppAsync","projectRoot","platforms","outputDir","clear","dev","dumpAssetmap","sourceMaps","minify","bytecode","maxWorkers","skipSSG","hostedNative","exp","environment","process","env","NODE_ENV","setNodeEnv","require","load","projectConfig","getConfig","getPublicExpoManifestAsync","skipValidation","length","includes","WebSupportProjectPrerequisite","assertAsync","useServerRendering","web","output","CommandError","baseUrl","getBaseUrlFromExpoConfig","Log","warn","log","chalk","gray","startsWith","yellow","mode","publicPath","path","resolve","EXPO_PUBLIC_FOLDER","outputPath","files","Map","devServerManager","DevServerManager","startMetroAsync","port","isExporting","location","resetDevServer","devServer","getDefaultDevServer","assert","MetroBundlerDevServer","bundles","domComponentAssetsMetadata","spaPlatforms","isReactServerComponentsEnabled","filter","platform","copyPublicFolderAsync","join","error","templateHtml","Promise","all","map","isHermes","isEnableHermesManaged","assertEngineMismatchAsync","bundle","nativeExportBundleAsync","splitChunks","EXPO_NO_BUNDLE_SPLITTING","mainModuleName","getEntryWithServerRoot","pkg","engine","undefined","serializerIncludeMaps","reactCompiler","experiments","hosted","Error","exception","exit","getFilesFromSerialAssets","artifacts","includeSourceMaps","isServerHosted","expoDomComponentReferences","artifact","Array","isArray","metadata","flat","filePath","platformDomComponentsBundle","htmlOutputName","exportDomComponentAsync","useMd5Filename","assets","push","transformNativeBundleForMd5Filename","domComponentReference","nativeBundle","addDomBundleToMetadataAsync","transformDomEntryForMd5Filename","html","serializeHtmlWithAssets","resources","template","createTemplateHtmlFromExpoConfigAsync","scripts","cssLinks","modifyHtml","getVirtualFaviconAssetsAsync","set","contents","targetDomain","isWeb","exportApiRoutesStandaloneAsync","apiRoutesOnly","embeddedHashSet","exportAssetsAsync","JSON","stringify","createAssetMap","fileNames","Object","fromEntries","entries","asset","type","filename","createMetadataJson","exportServer","placeholderIndex","fs","existsSync","exportFromServerAsync","routerRoot","getRouterDirectoryModuleIdWithManifest","stopAsync","persistMetroFilesAsync"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/export/exportApp.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport type { Platform } from '@expo/config';\nimport { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { type PlatformMetadata, createMetadataJson } from './createMetadataJson';\nimport { exportAssetsAsync } from './exportAssets';\nimport {\n addDomBundleToMetadataAsync,\n exportDomComponentAsync,\n transformNativeBundleForMd5Filename,\n transformDomEntryForMd5Filename,\n} from './exportDomComponents';\nimport { assertEngineMismatchAsync, isEnableHermesManaged } from './exportHermes';\nimport {\n exportApiRoutesStandaloneAsync,\n exportFromServerAsync,\n injectScriptTags,\n} from './exportStaticAsync';\nimport { getVirtualFaviconAssetsAsync } from './favicon';\nimport { getPublicExpoManifestAsync } from './getPublicExpoManifest';\nimport { copyPublicFolderAsync, getPublicFolderPath } from './publicFolder';\nimport type { Options } from './resolveOptions';\nimport type { ExportAssetMap, BundleOutput, BundleAssetWithFileHashes } from './saveAssets';\nimport { getFilesFromSerialAssets, persistMetroFilesAsync } from './saveAssets';\nimport { createAssetMap } from './writeContents';\nimport * as Log from '../log';\nimport { WebSupportProjectPrerequisite } from '../start/doctor/web/WebSupportProjectPrerequisite';\nimport { DevServerManager } from '../start/server/DevServerManager';\nimport { MetroBundlerDevServer } from '../start/server/metro/MetroBundlerDevServer';\nimport { getRouterDirectoryModuleIdWithManifest } from '../start/server/metro/router';\nimport { serializeHtmlWithAssets } from '../start/server/metro/serializeHtml';\nimport { getEntryWithServerRoot } from '../start/server/middleware/ManifestMiddleware';\nimport { getBaseUrlFromExpoConfig } from '../start/server/middleware/metroOptions';\nimport { createTemplateHtmlFromExpoConfigAsync } from '../start/server/webTemplate';\nimport { env } from '../utils/env';\nimport { CommandError } from '../utils/errors';\nimport { setNodeEnv } from '../utils/nodeEnv';\n\nexport async function exportAppAsync(\n projectRoot: string,\n {\n platforms,\n outputDir,\n clear,\n dev,\n dumpAssetmap,\n sourceMaps,\n minify,\n bytecode,\n maxWorkers,\n skipSSG,\n hostedNative,\n }: Pick<\n Options,\n | 'dumpAssetmap'\n | 'sourceMaps'\n | 'dev'\n | 'clear'\n | 'outputDir'\n | 'platforms'\n | 'minify'\n | 'bytecode'\n | 'maxWorkers'\n | 'skipSSG'\n | 'hostedNative'\n >\n): Promise<void> {\n // Force the environment during export and do not allow overriding it.\n const environment = dev ? 'development' : 'production';\n process.env.NODE_ENV = environment;\n setNodeEnv(environment);\n\n require('@expo/env').load(projectRoot);\n\n const projectConfig = getConfig(projectRoot);\n const exp = await getPublicExpoManifestAsync(projectRoot, {\n // Web doesn't require validation.\n skipValidation: platforms.length === 1 && platforms[0] === 'web',\n });\n\n if (platforms.includes('web')) {\n await new WebSupportProjectPrerequisite(projectRoot).assertAsync();\n }\n\n const useServerRendering = ['static', 'server'].includes(exp.web?.output ?? '');\n\n if (skipSSG && exp.web?.output !== 'server') {\n throw new CommandError('--no-ssg can only be used with `web.output: server`');\n }\n\n const baseUrl = getBaseUrlFromExpoConfig(exp);\n\n if (!bytecode && (platforms.includes('ios') || platforms.includes('android'))) {\n Log.warn(\n `Bytecode makes the app startup faster, disabling bytecode is highly discouraged and should only be used for debugging purposes.`\n );\n }\n\n // Print out logs\n if (baseUrl) {\n Log.log();\n Log.log(chalk.gray`Using (experimental) base path: ${baseUrl}`);\n // Warn if not using an absolute path.\n if (!baseUrl.startsWith('/')) {\n Log.log(\n chalk.yellow` Base path does not start with a slash. Requests will not be absolute.`\n );\n }\n }\n\n const mode = dev ? 'development' : 'production';\n const publicPath = getPublicFolderPath(projectRoot);\n const outputPath = path.resolve(projectRoot, outputDir);\n\n // Write the JS bundles to disk, and get the bundle file names (this could change with async chunk loading support).\n\n const files: ExportAssetMap = new Map();\n\n const devServerManager = await DevServerManager.startMetroAsync(projectRoot, {\n minify,\n mode,\n port: 8081,\n isExporting: true,\n location: {},\n resetDevServer: clear,\n maxWorkers,\n });\n\n const devServer = devServerManager.getDefaultDevServer();\n assert(devServer instanceof MetroBundlerDevServer);\n\n const bundles: Partial<Record<Platform, BundleOutput>> = {};\n const domComponentAssetsMetadata: Partial<Record<Platform, PlatformMetadata['assets']>> = {};\n\n const spaPlatforms =\n // TODO: Support server and static rendering for server component exports.\n useServerRendering && !devServer.isReactServerComponentsEnabled\n ? platforms.filter((platform) => platform !== 'web')\n : platforms;\n\n try {\n if (devServer.isReactServerComponentsEnabled) {\n // In RSC mode, we only need these to be in the client dir.\n // TODO: Merge back with other copy after we add SSR.\n try {\n await copyPublicFolderAsync(publicPath, path.join(outputPath, 'client'));\n } catch (error) {\n Log.error('Failed to copy public directory to dist directory');\n throw error;\n }\n } else {\n // NOTE(kitten): The public folder is currently always copied, regardless of targetDomain\n // split. Hence, there's another separate `copyPublicFolderAsync` call below for `web`\n await copyPublicFolderAsync(publicPath, outputPath);\n }\n\n let templateHtml: string | undefined;\n // Can be empty during web-only SSG.\n if (spaPlatforms.length) {\n await Promise.all(\n spaPlatforms.map(async (platform) => {\n // Assert early so the user doesn't have to wait until bundling is complete to find out that\n // Hermes won't be available.\n const isHermes = isEnableHermesManaged(exp, platform);\n if (isHermes) {\n await assertEngineMismatchAsync(projectRoot, exp, platform);\n }\n\n let bundle: {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n files?: ExportAssetMap;\n };\n\n try {\n // Run metro bundler and create the JS bundles/source maps.\n bundle = await devServer.nativeExportBundleAsync(\n exp,\n {\n platform,\n splitChunks:\n !env.EXPO_NO_BUNDLE_SPLITTING &&\n ((devServer.isReactServerComponentsEnabled && !bytecode) || platform === 'web'),\n mainModuleName: getEntryWithServerRoot(projectRoot, {\n platform,\n pkg: projectConfig.pkg,\n }),\n mode: dev ? 'development' : 'production',\n engine: isHermes ? 'hermes' : undefined,\n serializerIncludeMaps: sourceMaps,\n bytecode: bytecode && isHermes,\n reactCompiler: !!exp.experiments?.reactCompiler,\n hosted: hostedNative,\n },\n files\n );\n } catch (error) {\n Log.log('');\n if (error instanceof Error) {\n Log.exception(error);\n } else {\n Log.error('Failed to bundle the app');\n Log.log(error as any);\n }\n process.exit(1);\n }\n\n bundles[platform] = bundle;\n\n getFilesFromSerialAssets(bundle.artifacts, {\n includeSourceMaps: sourceMaps,\n files,\n isServerHosted: devServer.isReactServerComponentsEnabled || hostedNative,\n });\n\n // TODO: Remove duplicates...\n const expoDomComponentReferences = bundle.artifacts\n .map((artifact) =>\n Array.isArray(artifact.metadata.expoDomComponentReferences)\n ? artifact.metadata.expoDomComponentReferences\n : []\n )\n .flat();\n await Promise.all(\n // TODO: Make a version of this which uses `this.metro.getBundler().buildGraphForEntries([])` to bundle all the DOM components at once.\n expoDomComponentReferences.map(async (filePath) => {\n const { bundle: platformDomComponentsBundle, htmlOutputName } =\n await exportDomComponentAsync({\n filePath,\n projectRoot,\n dev,\n devServer,\n isHermes,\n includeSourceMaps: sourceMaps,\n exp,\n files,\n useMd5Filename: true,\n });\n\n // Merge the assets from the DOM component into the output assets.\n // @ts-expect-error: mutate assets\n bundle.assets.push(...platformDomComponentsBundle.assets);\n\n transformNativeBundleForMd5Filename({\n domComponentReference: filePath,\n nativeBundle: bundle,\n files,\n htmlOutputName,\n });\n domComponentAssetsMetadata[platform] = [\n ...(domComponentAssetsMetadata[platform] || []),\n ...(await addDomBundleToMetadataAsync(platformDomComponentsBundle)),\n ...transformDomEntryForMd5Filename({\n files,\n htmlOutputName,\n }),\n ];\n })\n );\n\n if (platform === 'web') {\n // TODO: Unify with exportStaticAsync\n // TODO: Maybe move to the serializer.\n let html = await serializeHtmlWithAssets({\n isExporting: true,\n resources: bundle.artifacts,\n template: await createTemplateHtmlFromExpoConfigAsync(projectRoot, {\n scripts: [],\n cssLinks: [],\n exp: projectConfig.exp,\n }),\n baseUrl,\n });\n\n // Add the favicon assets to the HTML.\n const modifyHtml = await getVirtualFaviconAssetsAsync(projectRoot, {\n outputDir,\n baseUrl,\n files,\n exp: projectConfig.exp,\n });\n if (modifyHtml) {\n html = modifyHtml(html);\n }\n\n // HACK: This is used for adding SSR shims in React Server Components.\n templateHtml = html;\n\n // Generate SPA-styled HTML file.\n // If web exists, then write the template HTML file.\n files.set('index.html', {\n contents: html,\n targetDomain: devServer.isReactServerComponentsEnabled ? 'server' : 'client',\n });\n }\n })\n );\n\n if (devServer.isReactServerComponentsEnabled) {\n const isWeb = platforms.includes('web');\n\n await exportApiRoutesStandaloneAsync(devServer, {\n files,\n platform: 'web',\n apiRoutesOnly: !isWeb,\n templateHtml,\n });\n }\n\n // TODO: Use same asset system across platforms again.\n const { assets, embeddedHashSet } = await exportAssetsAsync(projectRoot, {\n files,\n exp,\n outputDir: outputPath,\n bundles,\n baseUrl,\n hostedNative,\n });\n\n if (dumpAssetmap) {\n Log.log('Creating asset map');\n files.set('assetmap.json', { contents: JSON.stringify(createAssetMap({ assets })) });\n }\n\n const targetDomain = devServer.isReactServerComponentsEnabled ? 'client/' : '';\n const fileNames = Object.fromEntries(\n Object.entries(bundles).map(([platform, bundle]) => [\n platform,\n bundle.artifacts\n .filter((asset) => asset.type === 'js')\n .map((asset) => targetDomain + asset.filename),\n ])\n );\n\n // Generate a `metadata.json` for EAS Update.\n const contents = createMetadataJson({\n bundles,\n fileNames,\n embeddedHashSet,\n domComponentAssetsMetadata,\n });\n files.set('metadata.json', { contents: JSON.stringify(contents) });\n }\n\n // Additional web-only steps...\n\n if (platforms.includes('web') && useServerRendering) {\n const exportServer = exp.web?.output === 'server';\n\n if (exportServer) {\n // TODO: Remove when this is abstracted into the files map\n await copyPublicFolderAsync(publicPath, path.resolve(outputPath, 'client'));\n }\n\n if (skipSSG) {\n Log.log('Skipping static site generation');\n await exportApiRoutesStandaloneAsync(devServer, {\n files,\n platform: 'web',\n apiRoutesOnly: true,\n });\n\n // Output a placeholder index.html if one doesn't exist in the public directory.\n // This ensures native + API routes have some content at the root URL.\n const placeholderIndex = path.resolve(outputPath, 'client/index.html');\n if (!fs.existsSync(placeholderIndex)) {\n files.set('index.html', {\n contents: `<html><body></body></html>`,\n targetDomain: 'client',\n });\n }\n } else if (\n // TODO: Support static export with RSC.\n !devServer.isReactServerComponentsEnabled\n ) {\n await exportFromServerAsync(projectRoot, devServer, {\n mode,\n files,\n clear: !!clear,\n outputDir: outputPath,\n minify,\n baseUrl,\n includeSourceMaps: sourceMaps,\n routerRoot: getRouterDirectoryModuleIdWithManifest(projectRoot, exp),\n reactCompiler: !!exp.experiments?.reactCompiler,\n exportServer,\n maxWorkers,\n isExporting: true,\n exp: projectConfig.exp,\n });\n }\n }\n } finally {\n await devServerManager.stopAsync();\n }\n\n // Write all files at the end for unified logging.\n await persistMetroFilesAsync(files, outputPath);\n}\n"],"names":["exportAppAsync","projectRoot","platforms","outputDir","clear","dev","dumpAssetmap","sourceMaps","minify","bytecode","maxWorkers","skipSSG","hostedNative","exp","environment","process","env","NODE_ENV","setNodeEnv","require","load","projectConfig","getConfig","getPublicExpoManifestAsync","skipValidation","length","includes","WebSupportProjectPrerequisite","assertAsync","useServerRendering","web","output","CommandError","baseUrl","getBaseUrlFromExpoConfig","Log","warn","log","chalk","gray","startsWith","yellow","mode","publicPath","getPublicFolderPath","outputPath","path","resolve","files","Map","devServerManager","DevServerManager","startMetroAsync","port","isExporting","location","resetDevServer","devServer","getDefaultDevServer","assert","MetroBundlerDevServer","bundles","domComponentAssetsMetadata","spaPlatforms","isReactServerComponentsEnabled","filter","platform","copyPublicFolderAsync","join","error","templateHtml","Promise","all","map","isHermes","isEnableHermesManaged","assertEngineMismatchAsync","bundle","nativeExportBundleAsync","splitChunks","EXPO_NO_BUNDLE_SPLITTING","mainModuleName","getEntryWithServerRoot","pkg","engine","undefined","serializerIncludeMaps","reactCompiler","experiments","hosted","Error","exception","exit","getFilesFromSerialAssets","artifacts","includeSourceMaps","isServerHosted","expoDomComponentReferences","artifact","Array","isArray","metadata","flat","filePath","platformDomComponentsBundle","htmlOutputName","exportDomComponentAsync","useMd5Filename","assets","push","transformNativeBundleForMd5Filename","domComponentReference","nativeBundle","addDomBundleToMetadataAsync","transformDomEntryForMd5Filename","html","serializeHtmlWithAssets","resources","template","createTemplateHtmlFromExpoConfigAsync","scripts","cssLinks","modifyHtml","getVirtualFaviconAssetsAsync","set","contents","targetDomain","isWeb","exportApiRoutesStandaloneAsync","apiRoutesOnly","embeddedHashSet","exportAssetsAsync","JSON","stringify","createAssetMap","fileNames","Object","fromEntries","entries","asset","type","filename","createMetadataJson","exportServer","placeholderIndex","fs","existsSync","exportFromServerAsync","routerRoot","getRouterDirectoryModuleIdWithManifest","stopAsync","persistMetroFilesAsync"],"mappings":"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"}
@@ -12,6 +12,9 @@ _export(exports, {
12
12
  copyPublicFolderAsync: function() {
13
13
  return copyPublicFolderAsync;
14
14
  },
15
+ getPublicFolderPath: function() {
16
+ return getPublicFolderPath;
17
+ },
15
18
  getUserDefinedFile: function() {
16
19
  return getUserDefinedFile;
17
20
  }
@@ -32,14 +35,29 @@ function _path() {
32
35
  }
33
36
  const _dir = require("../utils/dir");
34
37
  const _env = require("../utils/env");
38
+ const _errors = require("../utils/errors");
35
39
  function _interop_require_default(obj) {
36
40
  return obj && obj.__esModule ? obj : {
37
41
  default: obj
38
42
  };
39
43
  }
40
44
  const debug = require('debug')('expo:public-folder');
45
+ const maybeRealpath = (target)=>{
46
+ try {
47
+ return _fs().default.realpathSync(target);
48
+ } catch {
49
+ return target;
50
+ }
51
+ };
52
+ function getPublicFolderPath(projectRoot) {
53
+ const publicPath = maybeRealpath(_path().default.resolve(projectRoot, _env.env.EXPO_PUBLIC_FOLDER));
54
+ if (!(0, _dir.isPathInside)(publicPath, projectRoot)) {
55
+ throw new _errors.CommandError('EXPO_PUBLIC_FOLDER', `EXPO_PUBLIC_FOLDER ("${_env.env.EXPO_PUBLIC_FOLDER}") resolves to "${publicPath}", which is outside the project root "${projectRoot}". Set EXPO_PUBLIC_FOLDER to a path inside your project (e.g. "public").`);
56
+ }
57
+ return publicPath;
58
+ }
41
59
  function getUserDefinedFile(projectRoot, possiblePaths) {
42
- const publicPath = _path().default.join(projectRoot, _env.env.EXPO_PUBLIC_FOLDER);
60
+ const publicPath = getPublicFolderPath(projectRoot);
43
61
  for (const possiblePath of possiblePaths){
44
62
  const fullPath = _path().default.join(publicPath, possiblePath);
45
63
  if (_fs().default.existsSync(fullPath)) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/export/publicFolder.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { copyAsync } from '../utils/dir';\nimport { env } from '../utils/env';\n\nconst debug = require('debug')('expo:public-folder') as typeof console.log;\n\n/** @returns the file system path for a user-defined file in the public folder. */\nexport function getUserDefinedFile(projectRoot: string, possiblePaths: string[]): string | null {\n const publicPath = path.join(projectRoot, env.EXPO_PUBLIC_FOLDER);\n\n for (const possiblePath of possiblePaths) {\n const fullPath = path.join(publicPath, possiblePath);\n if (fs.existsSync(fullPath)) {\n debug(`Found user-defined public file: ` + possiblePath);\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Copy the contents of the public folder into the output folder.\n * This enables users to add static files like `favicon.ico`.\n *\n * The contents of this folder are completely universal since they refer to\n * static network requests which fall outside the scope of React Native's magic\n * platform resolution patterns.\n */\nexport async function copyPublicFolderAsync(publicFolder: string, outputFolder: string) {\n if (fs.existsSync(publicFolder)) {\n await fs.promises.mkdir(outputFolder, { recursive: true });\n await copyAsync(publicFolder, outputFolder);\n }\n}\n"],"names":["copyPublicFolderAsync","getUserDefinedFile","debug","require","projectRoot","possiblePaths","publicPath","path","join","env","EXPO_PUBLIC_FOLDER","possiblePath","fullPath","fs","existsSync","publicFolder","outputFolder","promises","mkdir","recursive","copyAsync"],"mappings":";;;;;;;;;;;IA+BsBA,qBAAqB;eAArBA;;IAtBNC,kBAAkB;eAAlBA;;;;gEATD;;;;;;;gEACE;;;;;;qBAES;qBACN;;;;;;AAEpB,MAAMC,QAAQC,QAAQ,SAAS;AAGxB,SAASF,mBAAmBG,WAAmB,EAAEC,aAAuB;IAC7E,MAAMC,aAAaC,eAAI,CAACC,IAAI,CAACJ,aAAaK,QAAG,CAACC,kBAAkB;IAEhE,KAAK,MAAMC,gBAAgBN,cAAe;QACxC,MAAMO,WAAWL,eAAI,CAACC,IAAI,CAACF,YAAYK;QACvC,IAAIE,aAAE,CAACC,UAAU,CAACF,WAAW;YAC3BV,MAAM,CAAC,gCAAgC,CAAC,GAAGS;YAC3C,OAAOC;QACT;IACF;IAEA,OAAO;AACT;AAUO,eAAeZ,sBAAsBe,YAAoB,EAAEC,YAAoB;IACpF,IAAIH,aAAE,CAACC,UAAU,CAACC,eAAe;QAC/B,MAAMF,aAAE,CAACI,QAAQ,CAACC,KAAK,CAACF,cAAc;YAAEG,WAAW;QAAK;QACxD,MAAMC,IAAAA,cAAS,EAACL,cAAcC;IAChC;AACF"}
1
+ {"version":3,"sources":["../../../src/export/publicFolder.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { copyAsync, isPathInside } from '../utils/dir';\nimport { env } from '../utils/env';\nimport { CommandError } from '../utils/errors';\n\nconst debug = require('debug')('expo:public-folder') as typeof console.log;\n\nconst maybeRealpath = (target: string) => {\n try {\n return fs.realpathSync(target);\n } catch {\n return target;\n }\n};\n\n/**\n * Resolve `EXPO_PUBLIC_FOLDER` against the project root and ensure the result\n * stays inside the project. An `EXPO_PUBLIC_FOLDER` value that escapes\n * (e.g. `../etc`, `/absolute/path`) almost always indicates a misconfigured\n * environment, and if honored would expose unrelated files via every consumer\n * that serves or copies the public folder.\n */\nexport function getPublicFolderPath(projectRoot: string): string {\n const publicPath = maybeRealpath(path.resolve(projectRoot, env.EXPO_PUBLIC_FOLDER));\n if (!isPathInside(publicPath, projectRoot)) {\n throw new CommandError(\n 'EXPO_PUBLIC_FOLDER',\n `EXPO_PUBLIC_FOLDER (\"${env.EXPO_PUBLIC_FOLDER}\") resolves to \"${publicPath}\", which is outside the project root \"${projectRoot}\". Set EXPO_PUBLIC_FOLDER to a path inside your project (e.g. \"public\").`\n );\n }\n return publicPath;\n}\n\n/** @returns the file system path for a user-defined file in the public folder. */\nexport function getUserDefinedFile(projectRoot: string, possiblePaths: string[]): string | null {\n const publicPath = getPublicFolderPath(projectRoot);\n\n for (const possiblePath of possiblePaths) {\n const fullPath = path.join(publicPath, possiblePath);\n if (fs.existsSync(fullPath)) {\n debug(`Found user-defined public file: ` + possiblePath);\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Copy the contents of the public folder into the output folder.\n * This enables users to add static files like `favicon.ico`.\n *\n * The contents of this folder are completely universal since they refer to\n * static network requests which fall outside the scope of React Native's magic\n * platform resolution patterns.\n */\nexport async function copyPublicFolderAsync(publicFolder: string, outputFolder: string) {\n if (fs.existsSync(publicFolder)) {\n await fs.promises.mkdir(outputFolder, { recursive: true });\n await copyAsync(publicFolder, outputFolder);\n }\n}\n"],"names":["copyPublicFolderAsync","getPublicFolderPath","getUserDefinedFile","debug","require","maybeRealpath","target","fs","realpathSync","projectRoot","publicPath","path","resolve","env","EXPO_PUBLIC_FOLDER","isPathInside","CommandError","possiblePaths","possiblePath","fullPath","join","existsSync","publicFolder","outputFolder","promises","mkdir","recursive","copyAsync"],"mappings":";;;;;;;;;;;IA0DsBA,qBAAqB;eAArBA;;IAlCNC,mBAAmB;eAAnBA;;IAYAC,kBAAkB;eAAlBA;;;;gEApCD;;;;;;;gEACE;;;;;;qBAEuB;qBACpB;wBACS;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AAE/B,MAAMC,gBAAgB,CAACC;IACrB,IAAI;QACF,OAAOC,aAAE,CAACC,YAAY,CAACF;IACzB,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AASO,SAASL,oBAAoBQ,WAAmB;IACrD,MAAMC,aAAaL,cAAcM,eAAI,CAACC,OAAO,CAACH,aAAaI,QAAG,CAACC,kBAAkB;IACjF,IAAI,CAACC,IAAAA,iBAAY,EAACL,YAAYD,cAAc;QAC1C,MAAM,IAAIO,oBAAY,CACpB,sBACA,CAAC,qBAAqB,EAAEH,QAAG,CAACC,kBAAkB,CAAC,gBAAgB,EAAEJ,WAAW,sCAAsC,EAAED,YAAY,wEAAwE,CAAC;IAE7M;IACA,OAAOC;AACT;AAGO,SAASR,mBAAmBO,WAAmB,EAAEQ,aAAuB;IAC7E,MAAMP,aAAaT,oBAAoBQ;IAEvC,KAAK,MAAMS,gBAAgBD,cAAe;QACxC,MAAME,WAAWR,eAAI,CAACS,IAAI,CAACV,YAAYQ;QACvC,IAAIX,aAAE,CAACc,UAAU,CAACF,WAAW;YAC3BhB,MAAM,CAAC,gCAAgC,CAAC,GAAGe;YAC3C,OAAOC;QACT;IACF;IAEA,OAAO;AACT;AAUO,eAAenB,sBAAsBsB,YAAoB,EAAEC,YAAoB;IACpF,IAAIhB,aAAE,CAACc,UAAU,CAACC,eAAe;QAC/B,MAAMf,aAAE,CAACiB,QAAQ,CAACC,KAAK,CAACF,cAAc;YAAEG,WAAW;QAAK;QACxD,MAAMC,IAAAA,cAAS,EAACL,cAAcC;IAChC;AACF"}
@@ -22,13 +22,12 @@ function _semver() {
22
22
  };
23
23
  return data;
24
24
  }
25
- const _client = require("../api/rest/client");
26
25
  const _log = /*#__PURE__*/ _interop_require_wildcard(require("../log"));
27
26
  const _resolveLocalTemplate = require("./resolveLocalTemplate");
28
27
  const _createFileTransform = require("../utils/createFileTransform");
29
28
  const _errors = require("../utils/errors");
29
+ const _fetch = require("../utils/fetch");
30
30
  const _npm = require("../utils/npm");
31
- const _url = require("../utils/url");
32
31
  function _interop_require_default(obj) {
33
32
  return obj && obj.__esModule ? obj : {
34
33
  default: obj
@@ -125,8 +124,9 @@ async function getRepoInfo(url, examplePath) {
125
124
  const filePath = examplePath ? examplePath.replace(/^\//, '') : file.join('/');
126
125
  // Support repos whose entire purpose is to be an example, e.g.
127
126
  // https://github.com/:username/:my-cool-example-repo-name.
127
+ // Use the plain unauthenticated `fetch` so Expo credentials aren't forwarded to GitHub.
128
128
  if (t === undefined) {
129
- const infoResponse = await (0, _client.fetchAsync)(`https://api.github.com/repos/${username}/${name}`);
129
+ const infoResponse = await (0, _fetch.fetch)(`https://api.github.com/repos/${username}/${name}`);
130
130
  if (infoResponse.status !== 200) {
131
131
  return;
132
132
  }
@@ -150,10 +150,15 @@ async function getRepoInfo(url, examplePath) {
150
150
  }
151
151
  return undefined;
152
152
  }
153
- function hasRepo({ username, name, branch, filePath }) {
153
+ async function hasRepo({ username, name, branch, filePath }) {
154
154
  const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;
155
155
  const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;
156
- return (0, _url.isUrlOk)(contentsUrl + packagePath + `?ref=${branch}`);
156
+ try {
157
+ const response = await (0, _fetch.fetch)(contentsUrl + packagePath + `?ref=${branch}`);
158
+ return response.ok;
159
+ } catch {
160
+ return false;
161
+ }
157
162
  }
158
163
  async function downloadAndExtractRepoAsync({ username, name, branch, filePath }, props) {
159
164
  const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/prebuild/resolveTemplate.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport { Ora } from 'ora';\nimport semver from 'semver';\n\nimport { type ResolvedTemplateOption } from './resolveOptions';\nimport { fetchAsync } from '../api/rest/client';\nimport * as Log from '../log';\nimport { resolveLocalTemplateAsync } from './resolveLocalTemplate';\nimport { createGlobFilter } from '../utils/createFileTransform';\nimport { AbortCommandError } from '../utils/errors';\nimport {\n ExtractProps,\n downloadAndExtractNpmModuleAsync,\n extractLocalNpmTarballAsync,\n extractNpmTarballFromUrlAsync,\n} from '../utils/npm';\nimport { isUrlOk } from '../utils/url';\n\nconst debug = require('debug')('expo:prebuild:resolveTemplate') as typeof console.log;\n\ntype RepoInfo = {\n username: string;\n name: string;\n branch: string;\n filePath: string;\n};\n\nexport async function cloneTemplateAsync({\n templateDirectory,\n projectRoot,\n template,\n exp,\n ora,\n}: {\n templateDirectory: string;\n projectRoot: string;\n template?: ResolvedTemplateOption;\n exp: Pick<ExpoConfig, 'name' | 'sdkVersion'>;\n ora: Ora;\n}): Promise<string> {\n if (template) {\n const appName = exp.name;\n const { type, uri } = template;\n if (type === 'file') {\n return await extractLocalNpmTarballAsync(uri, {\n cwd: templateDirectory,\n name: appName,\n });\n } else if (type === 'npm') {\n return await downloadAndExtractNpmModuleAsync(uri, {\n cwd: templateDirectory,\n name: appName,\n });\n } else if (type === 'repository') {\n return await resolveAndDownloadRepoTemplateAsync(templateDirectory, ora, appName, uri);\n } else {\n throw new Error(`Unknown template type: ${type}`);\n }\n } else {\n try {\n return await resolveLocalTemplateAsync({ templateDirectory, projectRoot, exp });\n } catch (error: any) {\n const templatePackageName = getTemplateNpmPackageNameFromSdkVersion(exp.sdkVersion);\n debug('Fallback to SDK template:', templatePackageName);\n return await downloadAndExtractNpmModuleAsync(templatePackageName, {\n cwd: templateDirectory,\n name: exp.name,\n });\n }\n }\n}\n\n/** Given an `sdkVersion` like `44.0.0` return a fully qualified NPM package name like: `expo-template-bare-minimum@sdk-44` */\nfunction getTemplateNpmPackageNameFromSdkVersion(sdkVersion?: string): string {\n // When undefined or UNVERSIONED, we use the latest version.\n if (!sdkVersion || sdkVersion === 'UNVERSIONED') {\n Log.log('Using an unspecified Expo SDK version. The latest template will be used.');\n return `expo-template-bare-minimum@latest`;\n }\n return `expo-template-bare-minimum@sdk-${semver.major(sdkVersion)}`;\n}\n\nasync function getRepoInfo(url: any, examplePath?: string): Promise<RepoInfo | undefined> {\n const [, username, name, t, _branch, ...file] = url.pathname.split('/');\n const filePath = examplePath ? examplePath.replace(/^\\//, '') : file.join('/');\n\n // Support repos whose entire purpose is to be an example, e.g.\n // https://github.com/:username/:my-cool-example-repo-name.\n if (t === undefined) {\n const infoResponse = await fetchAsync(`https://api.github.com/repos/${username}/${name}`);\n if (infoResponse.status !== 200) {\n return;\n }\n const info: any = await infoResponse.json();\n return { username, name, branch: info['default_branch'], filePath };\n }\n\n // If examplePath is available, the branch name takes the entire path\n const branch = examplePath\n ? `${_branch}/${file.join('/')}`.replace(new RegExp(`/${filePath}|/$`), '')\n : _branch;\n\n if (username && name && branch && t === 'tree') {\n return { username, name, branch, filePath };\n }\n return undefined;\n}\n\nfunction hasRepo({ username, name, branch, filePath }: RepoInfo) {\n const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;\n const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;\n\n return isUrlOk(contentsUrl + packagePath + `?ref=${branch}`);\n}\n\nasync function downloadAndExtractRepoAsync(\n { username, name, branch, filePath }: RepoInfo,\n props: ExtractProps\n): Promise<string> {\n const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;\n\n debug('Downloading tarball from:', url);\n\n // Extract the (sub)directory into non-empty path segments\n const directory = filePath.replace(/^\\//, '').split('/').filter(Boolean);\n // Remove the (sub)directory paths, and the root folder added by GitHub\n const strip = directory.length + 1;\n // Only extract the relevant (sub)directories, ignoring irrelevant files\n // The filder auto-ignores dotfiles, unless explicitly included\n const filter = createGlobFilter(\n !directory.length\n ? ['*/**', '*/ios/.xcode.env']\n : [`*/${directory.join('/')}/**`, `*/${directory.join('/')}/ios/.xcode.env`],\n {\n // Always ignore the `.xcworkspace` folder\n ignore: ['**/ios/*.xcworkspace/**'],\n }\n );\n\n return await extractNpmTarballFromUrlAsync(url, { ...props, strip, filter });\n}\n\nasync function resolveAndDownloadRepoTemplateAsync(\n templateDirectory: string,\n oraInstance: Ora,\n appName: string,\n template: string,\n templatePath?: string\n) {\n let repoUrl: URL | undefined;\n\n try {\n repoUrl = new URL(template);\n } catch (error: any) {\n if (error.code !== 'ERR_INVALID_URL') {\n oraInstance.fail(error);\n throw error;\n }\n }\n if (!repoUrl) {\n oraInstance.fail(`Invalid URL: ${chalk.red(`\"${template}\"`)}. Try again with a valid URL.`);\n throw new AbortCommandError();\n }\n\n if (repoUrl.origin !== 'https://github.com') {\n oraInstance.fail(\n `Invalid URL: ${chalk.red(\n `\"${template}\"`\n )}. Only GitHub repositories are supported. Try again with a valid GitHub URL.`\n );\n throw new AbortCommandError();\n }\n\n const repoInfo = await getRepoInfo(repoUrl, templatePath);\n\n if (!repoInfo) {\n oraInstance.fail(\n `Found invalid GitHub URL: ${chalk.red(`\"${template}\"`)}. Fix the URL and try again.`\n );\n throw new AbortCommandError();\n }\n\n const found = await hasRepo(repoInfo);\n\n if (!found) {\n oraInstance.fail(\n `Could not locate the repository for ${chalk.red(\n `\"${template}\"`\n )}. Check that the repository exists and try again.`\n );\n throw new AbortCommandError();\n }\n\n oraInstance.text = chalk.bold(\n `Downloading files from repo ${chalk.cyan(template)}. This might take a moment.`\n );\n\n return await downloadAndExtractRepoAsync(repoInfo, {\n cwd: templateDirectory,\n name: appName,\n });\n}\n"],"names":["cloneTemplateAsync","debug","require","templateDirectory","projectRoot","template","exp","ora","appName","name","type","uri","extractLocalNpmTarballAsync","cwd","downloadAndExtractNpmModuleAsync","resolveAndDownloadRepoTemplateAsync","Error","resolveLocalTemplateAsync","error","templatePackageName","getTemplateNpmPackageNameFromSdkVersion","sdkVersion","Log","log","semver","major","getRepoInfo","url","examplePath","username","t","_branch","file","pathname","split","filePath","replace","join","undefined","infoResponse","fetchAsync","status","info","json","branch","RegExp","hasRepo","contentsUrl","packagePath","isUrlOk","downloadAndExtractRepoAsync","props","directory","filter","Boolean","strip","length","createGlobFilter","ignore","extractNpmTarballFromUrlAsync","oraInstance","templatePath","repoUrl","URL","code","fail","chalk","red","AbortCommandError","origin","repoInfo","found","text","bold","cyan"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/prebuild/resolveTemplate.ts"],"sourcesContent":["import type { ExpoConfig } from '@expo/config';\nimport chalk from 'chalk';\nimport type { Ora } from 'ora';\nimport semver from 'semver';\n\nimport type { ResolvedTemplateOption } from './resolveOptions';\nimport * as Log from '../log';\nimport { resolveLocalTemplateAsync } from './resolveLocalTemplate';\nimport { createGlobFilter } from '../utils/createFileTransform';\nimport { AbortCommandError } from '../utils/errors';\nimport { fetch } from '../utils/fetch';\nimport {\n ExtractProps,\n downloadAndExtractNpmModuleAsync,\n extractLocalNpmTarballAsync,\n extractNpmTarballFromUrlAsync,\n} from '../utils/npm';\n\nconst debug = require('debug')('expo:prebuild:resolveTemplate') as typeof console.log;\n\ntype RepoInfo = {\n username: string;\n name: string;\n branch: string;\n filePath: string;\n};\n\nexport async function cloneTemplateAsync({\n templateDirectory,\n projectRoot,\n template,\n exp,\n ora,\n}: {\n templateDirectory: string;\n projectRoot: string;\n template?: ResolvedTemplateOption;\n exp: Pick<ExpoConfig, 'name' | 'sdkVersion'>;\n ora: Ora;\n}): Promise<string> {\n if (template) {\n const appName = exp.name;\n const { type, uri } = template;\n if (type === 'file') {\n return await extractLocalNpmTarballAsync(uri, {\n cwd: templateDirectory,\n name: appName,\n });\n } else if (type === 'npm') {\n return await downloadAndExtractNpmModuleAsync(uri, {\n cwd: templateDirectory,\n name: appName,\n });\n } else if (type === 'repository') {\n return await resolveAndDownloadRepoTemplateAsync(templateDirectory, ora, appName, uri);\n } else {\n throw new Error(`Unknown template type: ${type}`);\n }\n } else {\n try {\n return await resolveLocalTemplateAsync({ templateDirectory, projectRoot, exp });\n } catch (error: any) {\n const templatePackageName = getTemplateNpmPackageNameFromSdkVersion(exp.sdkVersion);\n debug('Fallback to SDK template:', templatePackageName);\n return await downloadAndExtractNpmModuleAsync(templatePackageName, {\n cwd: templateDirectory,\n name: exp.name,\n });\n }\n }\n}\n\n/** Given an `sdkVersion` like `44.0.0` return a fully qualified NPM package name like: `expo-template-bare-minimum@sdk-44` */\nfunction getTemplateNpmPackageNameFromSdkVersion(sdkVersion?: string): string {\n // When undefined or UNVERSIONED, we use the latest version.\n if (!sdkVersion || sdkVersion === 'UNVERSIONED') {\n Log.log('Using an unspecified Expo SDK version. The latest template will be used.');\n return `expo-template-bare-minimum@latest`;\n }\n return `expo-template-bare-minimum@sdk-${semver.major(sdkVersion)}`;\n}\n\nasync function getRepoInfo(url: any, examplePath?: string): Promise<RepoInfo | undefined> {\n const [, username, name, t, _branch, ...file] = url.pathname.split('/');\n const filePath = examplePath ? examplePath.replace(/^\\//, '') : file.join('/');\n\n // Support repos whose entire purpose is to be an example, e.g.\n // https://github.com/:username/:my-cool-example-repo-name.\n // Use the plain unauthenticated `fetch` so Expo credentials aren't forwarded to GitHub.\n if (t === undefined) {\n const infoResponse = await fetch(`https://api.github.com/repos/${username}/${name}`);\n if (infoResponse.status !== 200) {\n return;\n }\n const info: any = await infoResponse.json();\n return { username, name, branch: info['default_branch'], filePath };\n }\n\n // If examplePath is available, the branch name takes the entire path\n const branch = examplePath\n ? `${_branch}/${file.join('/')}`.replace(new RegExp(`/${filePath}|/$`), '')\n : _branch;\n\n if (username && name && branch && t === 'tree') {\n return { username, name, branch, filePath };\n }\n return undefined;\n}\n\nasync function hasRepo({ username, name, branch, filePath }: RepoInfo): Promise<boolean> {\n const contentsUrl = `https://api.github.com/repos/${username}/${name}/contents`;\n const packagePath = `${filePath ? `/${filePath}` : ''}/package.json`;\n\n try {\n const response = await fetch(contentsUrl + packagePath + `?ref=${branch}`);\n return response.ok;\n } catch {\n return false;\n }\n}\n\nasync function downloadAndExtractRepoAsync(\n { username, name, branch, filePath }: RepoInfo,\n props: ExtractProps\n): Promise<string> {\n const url = `https://codeload.github.com/${username}/${name}/tar.gz/${branch}`;\n\n debug('Downloading tarball from:', url);\n\n // Extract the (sub)directory into non-empty path segments\n const directory = filePath.replace(/^\\//, '').split('/').filter(Boolean);\n // Remove the (sub)directory paths, and the root folder added by GitHub\n const strip = directory.length + 1;\n // Only extract the relevant (sub)directories, ignoring irrelevant files\n // The filder auto-ignores dotfiles, unless explicitly included\n const filter = createGlobFilter(\n !directory.length\n ? ['*/**', '*/ios/.xcode.env']\n : [`*/${directory.join('/')}/**`, `*/${directory.join('/')}/ios/.xcode.env`],\n {\n // Always ignore the `.xcworkspace` folder\n ignore: ['**/ios/*.xcworkspace/**'],\n }\n );\n\n return await extractNpmTarballFromUrlAsync(url, { ...props, strip, filter });\n}\n\nasync function resolveAndDownloadRepoTemplateAsync(\n templateDirectory: string,\n oraInstance: Ora,\n appName: string,\n template: string,\n templatePath?: string\n) {\n let repoUrl: URL | undefined;\n\n try {\n repoUrl = new URL(template);\n } catch (error: any) {\n if (error.code !== 'ERR_INVALID_URL') {\n oraInstance.fail(error);\n throw error;\n }\n }\n if (!repoUrl) {\n oraInstance.fail(`Invalid URL: ${chalk.red(`\"${template}\"`)}. Try again with a valid URL.`);\n throw new AbortCommandError();\n }\n\n if (repoUrl.origin !== 'https://github.com') {\n oraInstance.fail(\n `Invalid URL: ${chalk.red(\n `\"${template}\"`\n )}. Only GitHub repositories are supported. Try again with a valid GitHub URL.`\n );\n throw new AbortCommandError();\n }\n\n const repoInfo = await getRepoInfo(repoUrl, templatePath);\n\n if (!repoInfo) {\n oraInstance.fail(\n `Found invalid GitHub URL: ${chalk.red(`\"${template}\"`)}. Fix the URL and try again.`\n );\n throw new AbortCommandError();\n }\n\n const found = await hasRepo(repoInfo);\n\n if (!found) {\n oraInstance.fail(\n `Could not locate the repository for ${chalk.red(\n `\"${template}\"`\n )}. Check that the repository exists and try again.`\n );\n throw new AbortCommandError();\n }\n\n oraInstance.text = chalk.bold(\n `Downloading files from repo ${chalk.cyan(template)}. This might take a moment.`\n );\n\n return await downloadAndExtractRepoAsync(repoInfo, {\n cwd: templateDirectory,\n name: appName,\n });\n}\n"],"names":["cloneTemplateAsync","debug","require","templateDirectory","projectRoot","template","exp","ora","appName","name","type","uri","extractLocalNpmTarballAsync","cwd","downloadAndExtractNpmModuleAsync","resolveAndDownloadRepoTemplateAsync","Error","resolveLocalTemplateAsync","error","templatePackageName","getTemplateNpmPackageNameFromSdkVersion","sdkVersion","Log","log","semver","major","getRepoInfo","url","examplePath","username","t","_branch","file","pathname","split","filePath","replace","join","undefined","infoResponse","fetch","status","info","json","branch","RegExp","hasRepo","contentsUrl","packagePath","response","ok","downloadAndExtractRepoAsync","props","directory","filter","Boolean","strip","length","createGlobFilter","ignore","extractNpmTarballFromUrlAsync","oraInstance","templatePath","repoUrl","URL","code","fail","chalk","red","AbortCommandError","origin","repoInfo","found","text","bold","cyan"],"mappings":"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"}
@@ -17,6 +17,9 @@ function _configplugins() {
17
17
  }
18
18
  const _AndroidAppIdResolver = require("../../start/platforms/android/AndroidAppIdResolver");
19
19
  const _errors = require("../../utils/errors");
20
+ function resolveCustomLaunchActivity(packageName, mainActivity) {
21
+ return mainActivity.startsWith('.') ? `${packageName}${mainActivity}` : mainActivity;
22
+ }
20
23
  async function getMainActivityAsync(projectRoot) {
21
24
  const filePath = await _configplugins().AndroidConfig.Paths.getAndroidManifestAsync(projectRoot);
22
25
  const androidManifest = await _configplugins().AndroidConfig.Manifest.readAndroidManifestAsync(filePath);
@@ -34,7 +37,7 @@ async function resolveLaunchPropsAsync(projectRoot, options) {
34
37
  const mainActivity = await getMainActivityAsync(projectRoot);
35
38
  const packageName = await new _AndroidAppIdResolver.AndroidAppIdResolver(projectRoot).getAppIdFromNativeAsync();
36
39
  const customAppId = options.appId;
37
- const launchActivity = customAppId && customAppId !== packageName ? `${customAppId}/${packageName}${mainActivity}` : `${packageName}/${mainActivity}`;
40
+ const launchActivity = customAppId && customAppId !== packageName ? `${customAppId}/${resolveCustomLaunchActivity(packageName, mainActivity)}` : `${packageName}/${mainActivity}`;
38
41
  return {
39
42
  mainActivity,
40
43
  launchActivity,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/run/android/resolveLaunchProps.ts"],"sourcesContent":["import { AndroidConfig } from '@expo/config-plugins';\n\nimport { AndroidAppIdResolver } from '../../start/platforms/android/AndroidAppIdResolver';\nimport { CommandError } from '../../utils/errors';\n\nexport interface LaunchProps {\n /**\n * The \"common\" Android package name, configured through the app manifest.\n * @see https://source.android.com/docs/core/architecture/hidl/code-style#package-names\n */\n packageName: string;\n /**\n * Optional customized application ID, used in product flavors.\n * @see https://developer.android.com/build/build-variants#change-app-id\n */\n customAppId?: string;\n /**\n * The main activity to launch, by default this is `.MainActivity`.\n * @see https://github.com/expo/expo/blob/c0aec226a43c0f186258a063a6145c3e52246f8a/templates/expo-template-bare-minimum/android/app/src/main/AndroidManifest.xml#L22\n */\n mainActivity: string;\n /**\n * The full launch activity reference used in the app intent to launch the app with `adb am start -n <launchActivity>`.\n * Usually, this is structured as `<package-name>/.<activity-name>`.\n * For product flavors, this is structured as `<custom-app-id>/<package-name>.<activity-name>`.\n * @see https://developer.android.com/studio/command-line/adb#IntentSpec\n */\n launchActivity: string;\n}\n\nasync function getMainActivityAsync(projectRoot: string): Promise<string> {\n const filePath = await AndroidConfig.Paths.getAndroidManifestAsync(projectRoot);\n const androidManifest = await AndroidConfig.Manifest.readAndroidManifestAsync(filePath);\n const runnableActivity = AndroidConfig.Manifest.getRunnableActivity(androidManifest);\n if (runnableActivity) {\n return runnableActivity.$['android:name'];\n }\n const mainActivity = AndroidConfig.Manifest.getMainActivity(androidManifest);\n if (!mainActivity) {\n throw new CommandError(\n 'ANDROID_MALFORMED',\n `${filePath} is missing a runnable activity element.`\n );\n }\n return mainActivity.$['android:name'];\n}\n\nexport async function resolveLaunchPropsAsync(\n projectRoot: string,\n options: { appId?: string }\n): Promise<LaunchProps> {\n const mainActivity = await getMainActivityAsync(projectRoot);\n const packageName = await new AndroidAppIdResolver(projectRoot).getAppIdFromNativeAsync();\n const customAppId = options.appId;\n\n const launchActivity =\n customAppId && customAppId !== packageName\n ? `${customAppId}/${packageName}${mainActivity}`\n : `${packageName}/${mainActivity}`;\n\n return {\n mainActivity,\n launchActivity,\n packageName,\n customAppId,\n };\n}\n"],"names":["resolveLaunchPropsAsync","getMainActivityAsync","projectRoot","filePath","AndroidConfig","Paths","getAndroidManifestAsync","androidManifest","Manifest","readAndroidManifestAsync","runnableActivity","getRunnableActivity","$","mainActivity","getMainActivity","CommandError","options","packageName","AndroidAppIdResolver","getAppIdFromNativeAsync","customAppId","appId","launchActivity"],"mappings":";;;;+BA+CsBA;;;eAAAA;;;;yBA/CQ;;;;;;sCAEO;wBACR;AA2B7B,eAAeC,qBAAqBC,WAAmB;IACrD,MAAMC,WAAW,MAAMC,8BAAa,CAACC,KAAK,CAACC,uBAAuB,CAACJ;IACnE,MAAMK,kBAAkB,MAAMH,8BAAa,CAACI,QAAQ,CAACC,wBAAwB,CAACN;IAC9E,MAAMO,mBAAmBN,8BAAa,CAACI,QAAQ,CAACG,mBAAmB,CAACJ;IACpE,IAAIG,kBAAkB;QACpB,OAAOA,iBAAiBE,CAAC,CAAC,eAAe;IAC3C;IACA,MAAMC,eAAeT,8BAAa,CAACI,QAAQ,CAACM,eAAe,CAACP;IAC5D,IAAI,CAACM,cAAc;QACjB,MAAM,IAAIE,oBAAY,CACpB,qBACA,GAAGZ,SAAS,wCAAwC,CAAC;IAEzD;IACA,OAAOU,aAAaD,CAAC,CAAC,eAAe;AACvC;AAEO,eAAeZ,wBACpBE,WAAmB,EACnBc,OAA2B;IAE3B,MAAMH,eAAe,MAAMZ,qBAAqBC;IAChD,MAAMe,cAAc,MAAM,IAAIC,0CAAoB,CAAChB,aAAaiB,uBAAuB;IACvF,MAAMC,cAAcJ,QAAQK,KAAK;IAEjC,MAAMC,iBACJF,eAAeA,gBAAgBH,cAC3B,GAAGG,YAAY,CAAC,EAAEH,cAAcJ,cAAc,GAC9C,GAAGI,YAAY,CAAC,EAAEJ,cAAc;IAEtC,OAAO;QACLA;QACAS;QACAL;QACAG;IACF;AACF"}
1
+ {"version":3,"sources":["../../../../src/run/android/resolveLaunchProps.ts"],"sourcesContent":["import { AndroidConfig } from '@expo/config-plugins';\n\nimport { AndroidAppIdResolver } from '../../start/platforms/android/AndroidAppIdResolver';\nimport { CommandError } from '../../utils/errors';\n\nexport interface LaunchProps {\n /**\n * The \"common\" Android package name, configured through the app manifest.\n * @see https://source.android.com/docs/core/architecture/hidl/code-style#package-names\n */\n packageName: string;\n /**\n * Optional customized application ID, used in product flavors.\n * @see https://developer.android.com/build/build-variants#change-app-id\n */\n customAppId?: string;\n /**\n * The main activity to launch, by default this is `.MainActivity`.\n * @see https://github.com/expo/expo/blob/c0aec226a43c0f186258a063a6145c3e52246f8a/templates/expo-template-bare-minimum/android/app/src/main/AndroidManifest.xml#L22\n */\n mainActivity: string;\n /**\n * The full launch activity reference used in the app intent to launch the app with `adb am start -n <launchActivity>`.\n * Usually, this is structured as `<package-name>/.<activity-name>`.\n * For product flavors, this is structured as `<custom-app-id>/<package-name>.<activity-name>`.\n * @see https://developer.android.com/studio/command-line/adb#IntentSpec\n */\n launchActivity: string;\n}\n\nfunction resolveCustomLaunchActivity(packageName: string, mainActivity: string): string {\n return mainActivity.startsWith('.') ? `${packageName}${mainActivity}` : mainActivity;\n}\n\nasync function getMainActivityAsync(projectRoot: string): Promise<string> {\n const filePath = await AndroidConfig.Paths.getAndroidManifestAsync(projectRoot);\n const androidManifest = await AndroidConfig.Manifest.readAndroidManifestAsync(filePath);\n const runnableActivity = AndroidConfig.Manifest.getRunnableActivity(androidManifest);\n if (runnableActivity) {\n return runnableActivity.$['android:name'];\n }\n const mainActivity = AndroidConfig.Manifest.getMainActivity(androidManifest);\n if (!mainActivity) {\n throw new CommandError(\n 'ANDROID_MALFORMED',\n `${filePath} is missing a runnable activity element.`\n );\n }\n return mainActivity.$['android:name'];\n}\n\nexport async function resolveLaunchPropsAsync(\n projectRoot: string,\n options: { appId?: string }\n): Promise<LaunchProps> {\n const mainActivity = await getMainActivityAsync(projectRoot);\n const packageName = await new AndroidAppIdResolver(projectRoot).getAppIdFromNativeAsync();\n const customAppId = options.appId;\n\n const launchActivity =\n customAppId && customAppId !== packageName\n ? `${customAppId}/${resolveCustomLaunchActivity(packageName, mainActivity)}`\n : `${packageName}/${mainActivity}`;\n\n return {\n mainActivity,\n launchActivity,\n packageName,\n customAppId,\n };\n}\n"],"names":["resolveLaunchPropsAsync","resolveCustomLaunchActivity","packageName","mainActivity","startsWith","getMainActivityAsync","projectRoot","filePath","AndroidConfig","Paths","getAndroidManifestAsync","androidManifest","Manifest","readAndroidManifestAsync","runnableActivity","getRunnableActivity","$","getMainActivity","CommandError","options","AndroidAppIdResolver","getAppIdFromNativeAsync","customAppId","appId","launchActivity"],"mappings":";;;;+BAmDsBA;;;eAAAA;;;;yBAnDQ;;;;;;sCAEO;wBACR;AA2B7B,SAASC,4BAA4BC,WAAmB,EAAEC,YAAoB;IAC5E,OAAOA,aAAaC,UAAU,CAAC,OAAO,GAAGF,cAAcC,cAAc,GAAGA;AAC1E;AAEA,eAAeE,qBAAqBC,WAAmB;IACrD,MAAMC,WAAW,MAAMC,8BAAa,CAACC,KAAK,CAACC,uBAAuB,CAACJ;IACnE,MAAMK,kBAAkB,MAAMH,8BAAa,CAACI,QAAQ,CAACC,wBAAwB,CAACN;IAC9E,MAAMO,mBAAmBN,8BAAa,CAACI,QAAQ,CAACG,mBAAmB,CAACJ;IACpE,IAAIG,kBAAkB;QACpB,OAAOA,iBAAiBE,CAAC,CAAC,eAAe;IAC3C;IACA,MAAMb,eAAeK,8BAAa,CAACI,QAAQ,CAACK,eAAe,CAACN;IAC5D,IAAI,CAACR,cAAc;QACjB,MAAM,IAAIe,oBAAY,CACpB,qBACA,GAAGX,SAAS,wCAAwC,CAAC;IAEzD;IACA,OAAOJ,aAAaa,CAAC,CAAC,eAAe;AACvC;AAEO,eAAehB,wBACpBM,WAAmB,EACnBa,OAA2B;IAE3B,MAAMhB,eAAe,MAAME,qBAAqBC;IAChD,MAAMJ,cAAc,MAAM,IAAIkB,0CAAoB,CAACd,aAAae,uBAAuB;IACvF,MAAMC,cAAcH,QAAQI,KAAK;IAEjC,MAAMC,iBACJF,eAAeA,gBAAgBpB,cAC3B,GAAGoB,YAAY,CAAC,EAAErB,4BAA4BC,aAAaC,eAAe,GAC1E,GAAGD,YAAY,CAAC,EAAEC,cAAc;IAEtC,OAAO;QACLA;QACAqB;QACAtB;QACAoB;IACF;AACF"}
@@ -112,7 +112,7 @@ class LockdowndClient extends _ServiceClient.ServiceClient {
112
112
  }
113
113
  }
114
114
  async startSession(pairRecord) {
115
- debug(`startSession: ${pairRecord}`);
115
+ debug('startSession');
116
116
  const resp = await this.protocolClient.sendMessage({
117
117
  Request: 'StartSession',
118
118
  HostID: pairRecord.HostID,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/run/ios/appleDevice/client/LockdowndClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2021 Expo, Inc.\n * Copyright (c) 2018 Drifty Co.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport Debug from 'debug';\nimport { Socket } from 'net';\nimport * as tls from 'tls';\n\nimport { ResponseError, ServiceClient } from './ServiceClient';\nimport { UsbmuxdPairRecord } from './UsbmuxdClient';\nimport { LockdownProtocolClient } from '../protocol/LockdownProtocol';\n\nconst debug = Debug('expo:apple-device:client:lockdownd');\n\nexport interface DeviceValues {\n BasebandCertId: number;\n BasebandKeyHashInformation: {\n AKeyStatus: number;\n SKeyHash: Buffer;\n SKeyStatus: number;\n };\n BasebandSerialNumber: Buffer;\n BasebandVersion: string;\n BoardId: number;\n BuildVersion: string;\n ChipID: number;\n ConnectionType: 'USB' | 'Network';\n DeviceClass: string;\n DeviceColor: string;\n DeviceName: string;\n DieID: number;\n HardwareModel: string;\n HasSiDP: boolean;\n PartitionType: string;\n ProductName: string;\n ProductType: string;\n ProductVersion: string;\n ProductionSOC: boolean;\n ProtocolVersion: string;\n TelephonyCapability: boolean;\n UniqueChipID: number;\n UniqueDeviceID: string;\n WiFiAddress: string;\n [key: string]: any;\n}\n\ninterface LockdowndServiceResponse {\n Request: 'StartService';\n Service: string;\n Port: number;\n EnableServiceSSL?: boolean; // Only on iOS 13+\n}\n\ninterface LockdowndSessionResponse {\n Request: 'StartSession';\n EnableSessionSSL: boolean;\n}\n\ninterface LockdowndAllValuesResponse {\n Request: 'GetValue';\n Value: DeviceValues;\n}\n\ninterface LockdowndValueResponse {\n Request: 'GetValue';\n Key: string;\n Value: string;\n}\n\ninterface LockdowndQueryTypeResponse {\n Request: 'QueryType';\n Type: string;\n}\n\nfunction isLockdowndServiceResponse(resp: any): resp is LockdowndServiceResponse {\n return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;\n}\n\nfunction isLockdowndSessionResponse(resp: any): resp is LockdowndSessionResponse {\n return resp.Request === 'StartSession';\n}\n\nfunction isLockdowndAllValuesResponse(resp: any): resp is LockdowndAllValuesResponse {\n return resp.Request === 'GetValue' && resp.Value !== undefined;\n}\n\nfunction isLockdowndValueResponse(resp: any): resp is LockdowndValueResponse {\n return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';\n}\n\nfunction isLockdowndQueryTypeResponse(resp: any): resp is LockdowndQueryTypeResponse {\n return resp.Request === 'QueryType' && resp.Type !== undefined;\n}\n\nexport class LockdowndClient extends ServiceClient<LockdownProtocolClient> {\n constructor(public socket: Socket) {\n super(socket, new LockdownProtocolClient(socket));\n }\n\n async startService(name: string) {\n debug(`startService: ${name}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartService',\n Service: name,\n });\n\n if (isLockdowndServiceResponse(resp)) {\n return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };\n } else {\n throw new ResponseError(`Error starting service ${name}`, resp);\n }\n }\n\n async startSession(pairRecord: UsbmuxdPairRecord) {\n debug(`startSession: ${pairRecord}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartSession',\n HostID: pairRecord.HostID,\n SystemBUID: pairRecord.SystemBUID,\n });\n\n if (isLockdowndSessionResponse(resp)) {\n if (resp.EnableSessionSSL) {\n this.protocolClient.socket = new tls.TLSSocket(this.protocolClient.socket, {\n secureContext: tls.createSecureContext({\n // Avoid using `secureProtocol` fixing the socket to a single TLS version.\n // Newer Node versions might not support older TLS versions.\n // By using the default `minVersion` and `maxVersion` options,\n // The socket will automatically use the appropriate TLS version.\n // See: https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions\n cert: pairRecord.RootCertificate,\n key: pairRecord.RootPrivateKey,\n }),\n });\n debug(`Socket upgraded to TLS connection`);\n }\n // TODO: save sessionID for StopSession?\n } else {\n throw new ResponseError('Error starting session', resp);\n }\n }\n\n async getAllValues() {\n debug(`getAllValues`);\n\n const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });\n\n if (isLockdowndAllValuesResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async getValue(val: string) {\n debug(`getValue: ${val}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'GetValue',\n Key: val,\n });\n\n if (isLockdowndValueResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async queryType() {\n debug('queryType');\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'QueryType',\n });\n\n if (isLockdowndQueryTypeResponse(resp)) {\n return resp.Type;\n } else {\n throw new ResponseError('Error getting lockdown query type', resp);\n }\n }\n\n async doHandshake(pairRecord: UsbmuxdPairRecord) {\n debug('doHandshake');\n\n // if (await this.lockdownQueryType() !== 'com.apple.mobile.lockdown') {\n // throw new CommandError('Invalid type received from lockdown handshake');\n // }\n // await this.getLockdownValue('ProductVersion');\n // TODO: validate pair and pair\n await this.startSession(pairRecord);\n }\n}\n"],"names":["LockdowndClient","debug","Debug","isLockdowndServiceResponse","resp","Request","Service","undefined","Port","isLockdowndSessionResponse","isLockdowndAllValuesResponse","Value","isLockdowndValueResponse","Key","isLockdowndQueryTypeResponse","Type","ServiceClient","constructor","socket","LockdownProtocolClient","startService","name","protocolClient","sendMessage","port","enableServiceSSL","EnableServiceSSL","ResponseError","startSession","pairRecord","HostID","SystemBUID","EnableSessionSSL","tls","TLSSocket","secureContext","createSecureContext","cert","RootCertificate","key","RootPrivateKey","getAllValues","getValue","val","queryType","doHandshake"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../src/run/ios/appleDevice/client/LockdowndClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2021 Expo, Inc.\n * Copyright (c) 2018 Drifty Co.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport Debug from 'debug';\nimport { Socket } from 'net';\nimport * as tls from 'tls';\n\nimport { ResponseError, ServiceClient } from './ServiceClient';\nimport { UsbmuxdPairRecord } from './UsbmuxdClient';\nimport { LockdownProtocolClient } from '../protocol/LockdownProtocol';\n\nconst debug = Debug('expo:apple-device:client:lockdownd');\n\nexport interface DeviceValues {\n BasebandCertId: number;\n BasebandKeyHashInformation: {\n AKeyStatus: number;\n SKeyHash: Buffer;\n SKeyStatus: number;\n };\n BasebandSerialNumber: Buffer;\n BasebandVersion: string;\n BoardId: number;\n BuildVersion: string;\n ChipID: number;\n ConnectionType: 'USB' | 'Network';\n DeviceClass: string;\n DeviceColor: string;\n DeviceName: string;\n DieID: number;\n HardwareModel: string;\n HasSiDP: boolean;\n PartitionType: string;\n ProductName: string;\n ProductType: string;\n ProductVersion: string;\n ProductionSOC: boolean;\n ProtocolVersion: string;\n TelephonyCapability: boolean;\n UniqueChipID: number;\n UniqueDeviceID: string;\n WiFiAddress: string;\n [key: string]: any;\n}\n\ninterface LockdowndServiceResponse {\n Request: 'StartService';\n Service: string;\n Port: number;\n EnableServiceSSL?: boolean; // Only on iOS 13+\n}\n\ninterface LockdowndSessionResponse {\n Request: 'StartSession';\n EnableSessionSSL: boolean;\n}\n\ninterface LockdowndAllValuesResponse {\n Request: 'GetValue';\n Value: DeviceValues;\n}\n\ninterface LockdowndValueResponse {\n Request: 'GetValue';\n Key: string;\n Value: string;\n}\n\ninterface LockdowndQueryTypeResponse {\n Request: 'QueryType';\n Type: string;\n}\n\nfunction isLockdowndServiceResponse(resp: any): resp is LockdowndServiceResponse {\n return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;\n}\n\nfunction isLockdowndSessionResponse(resp: any): resp is LockdowndSessionResponse {\n return resp.Request === 'StartSession';\n}\n\nfunction isLockdowndAllValuesResponse(resp: any): resp is LockdowndAllValuesResponse {\n return resp.Request === 'GetValue' && resp.Value !== undefined;\n}\n\nfunction isLockdowndValueResponse(resp: any): resp is LockdowndValueResponse {\n return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';\n}\n\nfunction isLockdowndQueryTypeResponse(resp: any): resp is LockdowndQueryTypeResponse {\n return resp.Request === 'QueryType' && resp.Type !== undefined;\n}\n\nexport class LockdowndClient extends ServiceClient<LockdownProtocolClient> {\n constructor(public socket: Socket) {\n super(socket, new LockdownProtocolClient(socket));\n }\n\n async startService(name: string) {\n debug(`startService: ${name}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartService',\n Service: name,\n });\n\n if (isLockdowndServiceResponse(resp)) {\n return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };\n } else {\n throw new ResponseError(`Error starting service ${name}`, resp);\n }\n }\n\n async startSession(pairRecord: UsbmuxdPairRecord) {\n debug('startSession');\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartSession',\n HostID: pairRecord.HostID,\n SystemBUID: pairRecord.SystemBUID,\n });\n\n if (isLockdowndSessionResponse(resp)) {\n if (resp.EnableSessionSSL) {\n this.protocolClient.socket = new tls.TLSSocket(this.protocolClient.socket, {\n secureContext: tls.createSecureContext({\n // Avoid using `secureProtocol` fixing the socket to a single TLS version.\n // Newer Node versions might not support older TLS versions.\n // By using the default `minVersion` and `maxVersion` options,\n // The socket will automatically use the appropriate TLS version.\n // See: https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions\n cert: pairRecord.RootCertificate,\n key: pairRecord.RootPrivateKey,\n }),\n });\n debug(`Socket upgraded to TLS connection`);\n }\n // TODO: save sessionID for StopSession?\n } else {\n throw new ResponseError('Error starting session', resp);\n }\n }\n\n async getAllValues() {\n debug(`getAllValues`);\n\n const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });\n\n if (isLockdowndAllValuesResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async getValue(val: string) {\n debug(`getValue: ${val}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'GetValue',\n Key: val,\n });\n\n if (isLockdowndValueResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async queryType() {\n debug('queryType');\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'QueryType',\n });\n\n if (isLockdowndQueryTypeResponse(resp)) {\n return resp.Type;\n } else {\n throw new ResponseError('Error getting lockdown query type', resp);\n }\n }\n\n async doHandshake(pairRecord: UsbmuxdPairRecord) {\n debug('doHandshake');\n\n // if (await this.lockdownQueryType() !== 'com.apple.mobile.lockdown') {\n // throw new CommandError('Invalid type received from lockdown handshake');\n // }\n // await this.getLockdownValue('ProductVersion');\n // TODO: validate pair and pair\n await this.startSession(pairRecord);\n }\n}\n"],"names":["LockdowndClient","debug","Debug","isLockdowndServiceResponse","resp","Request","Service","undefined","Port","isLockdowndSessionResponse","isLockdowndAllValuesResponse","Value","isLockdowndValueResponse","Key","isLockdowndQueryTypeResponse","Type","ServiceClient","constructor","socket","LockdownProtocolClient","startService","name","protocolClient","sendMessage","port","enableServiceSSL","EnableServiceSSL","ResponseError","startSession","pairRecord","HostID","SystemBUID","EnableSessionSSL","tls","TLSSocket","secureContext","createSecureContext","cert","RootCertificate","key","RootPrivateKey","getAllValues","getValue","val","queryType","doHandshake"],"mappings":"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"}
@@ -15,6 +15,9 @@ _export(exports, {
15
15
  adbArgs: function() {
16
16
  return adbArgs;
17
17
  },
18
+ adbShellArgs: function() {
19
+ return adbShellArgs;
20
+ },
18
21
  getAdbNameForDeviceIdAsync: function() {
19
22
  return getAdbNameForDeviceIdAsync;
20
23
  },
@@ -162,7 +165,7 @@ function logUnauthorized(device) {
162
165
  _log.warn(`\nThis computer is not authorized for developing on ${_chalk().default.bold(device.name)}. ${_chalk().default.dim((0, _link.learnMore)('https://expo.fyi/authorize-android-device'))}`);
163
166
  }
164
167
  async function isPackageInstalledAsync(device, androidPackage) {
165
- const packages = await getServer().runAsync(adbArgs(device.pid, 'shell', 'pm', 'list', 'packages', '--user', _env.env.EXPO_ADB_USER, androidPackage));
168
+ const packages = await getServer().runAsync(adbShellArgs(device.pid, 'pm', 'list', 'packages', '--user', _env.env.EXPO_ADB_USER, androidPackage));
166
169
  const lines = packages.split(/\r?\n/);
167
170
  for(let i = 0; i < lines.length; i++){
168
171
  const line = lines[i].trim();
@@ -173,8 +176,7 @@ async function isPackageInstalledAsync(device, androidPackage) {
173
176
  return false;
174
177
  }
175
178
  async function launchActivityAsync(device, { launchActivity, url }) {
176
- const args = [
177
- 'shell',
179
+ const command = [
178
180
  'am',
179
181
  'start',
180
182
  // FLAG_ACTIVITY_SINGLE_TOP -- If set, the activity will not be launched if it is already running at the top of the history stack.
@@ -185,16 +187,15 @@ async function launchActivityAsync(device, { launchActivity, url }) {
185
187
  launchActivity
186
188
  ];
187
189
  if (url) {
188
- args.push('-d', url);
190
+ command.push('-d', url);
189
191
  }
190
- return openAsync(adbArgs(device.pid, ...args));
192
+ return openAsync(adbShellArgs(device.pid, ...command));
191
193
  }
192
194
  async function openAppIdAsync(device, { applicationId }) {
193
195
  return openAsync(adbArgs(device.pid, 'shell', 'monkey', '-p', applicationId, '-c', 'android.intent.category.LAUNCHER', '1'));
194
196
  }
195
197
  async function openUrlAsync(device, { url }) {
196
- return openAsync(adbArgs(device.pid, 'shell', 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', // ADB requires ampersands to be escaped.
197
- url.replace(/&/g, String.raw`\&`)));
198
+ return openAsync(adbShellArgs(device.pid, 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', url));
198
199
  }
199
200
  /** Runs a generic command watches for common errors in order to throw with an expected code. */ async function openAsync(args) {
200
201
  const results = await getServer().runAsync(args);
@@ -207,7 +208,7 @@ async function uninstallAsync(device, { appId }) {
207
208
  return await getServer().runAsync(adbArgs(device.pid, 'uninstall', '--user', _env.env.EXPO_ADB_USER, appId));
208
209
  }
209
210
  async function getPackageInfoAsync(device, { appId }) {
210
- return await getServer().runAsync(adbArgs(device.pid, 'shell', 'dumpsys', 'package', appId));
211
+ return await getServer().runAsync(adbShellArgs(device.pid, 'dumpsys', 'package', appId));
211
212
  }
212
213
  async function installAsync(device, { filePath }) {
213
214
  // TODO: Handle the `INSTALL_FAILED_INSUFFICIENT_STORAGE` error.
@@ -220,6 +221,12 @@ function adbArgs(pid, ...options) {
220
221
  }
221
222
  return args.concat(options);
222
223
  }
224
+ function adbShellArgs(pid, ...command) {
225
+ return adbArgs(pid, 'shell', ...command.map(shellQuote));
226
+ }
227
+ function shellQuote(value) {
228
+ return `'${value.replace(/'/g, `'\\''`)}'`;
229
+ }
223
230
  async function getAttachedDevicesAsync() {
224
231
  const output = await getServer().runAsync([
225
232
  'devices',
@@ -331,13 +338,7 @@ async function getDeviceABIsAsync(device) {
331
338
  ];
332
339
  }
333
340
  async function getPropertyDataForDeviceAsync(device, prop) {
334
- // @ts-ignore
335
- const propCommand = adbArgs(...[
336
- device.pid,
337
- 'shell',
338
- 'getprop',
339
- prop
340
- ].filter(Boolean));
341
+ const propCommand = prop ? adbShellArgs(device.pid, 'getprop', prop) : adbShellArgs(device.pid, 'getprop');
341
342
  try {
342
343
  // Prevent reading as UTF8.
343
344
  const results = await getServer().getFileOutputAsync(propCommand);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/platforms/android/adb.ts"],"sourcesContent":["import chalk from 'chalk';\nimport os from 'os';\n\nimport { ADBServer } from './ADBServer';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\nimport { learnMore } from '../../../utils/link';\n\nconst debug = require('debug')('expo:start:platforms:android:adb') as typeof console.log;\n\nexport enum DeviceABI {\n // The arch specific android target platforms are soft-deprecated.\n // Instead of using TargetPlatform as a combination arch + platform\n // the code will be updated to carry arch information in [DarwinArch]\n // and [AndroidArch].\n arm = 'arm',\n arm64 = 'arm64',\n x64 = 'x64',\n x86 = 'x86',\n x8664 = 'x86_64',\n arm64v8a = 'arm64-v8a',\n armeabiV7a = 'armeabi-v7a',\n armeabi = 'armeabi',\n universal = 'universal',\n}\n\n/** Represents a connected Android device. */\nexport type Device = {\n /** Process ID. */\n pid?: string;\n /** Name of the device, also used as the ID for opening devices. */\n name: string;\n /** Is emulator or connected device. */\n type: 'emulator' | 'device';\n /** Is the device booted (emulator). */\n isBooted: boolean;\n /** Is device authorized for developing. https://expo.fyi/authorize-android-device */\n isAuthorized: boolean;\n /** The connection type to ADB, only available when `type: device` */\n connectionType?: 'USB' | 'Network';\n};\n\ntype DeviceContext = Pick<Device, 'pid'>;\n\ntype DeviceProperties = Record<string, string>;\n\nconst CANT_START_ACTIVITY_ERROR = 'Activity not started, unable to resolve Intent';\n// http://developer.android.com/ndk/guides/abis.html\nconst PROP_CPU_NAME = 'ro.product.cpu.abi';\n\nconst PROP_CPU_ABI_LIST_NAME = 'ro.product.cpu.abilist';\n\n// Can sometimes be null\n// http://developer.android.com/ndk/guides/abis.html\nconst PROP_BOOT_ANIMATION_STATE = 'init.svc.bootanim';\n\nlet _server: ADBServer | null;\n\n/** Return the lazily loaded ADB server instance. */\nexport function getServer() {\n _server ??= new ADBServer();\n return _server;\n}\n\n/** Logs an FYI message about authorizing your device. */\nexport function logUnauthorized(device: Device) {\n Log.warn(\n `\\nThis computer is not authorized for developing on ${chalk.bold(device.name)}. ${chalk.dim(\n learnMore('https://expo.fyi/authorize-android-device')\n )}`\n );\n}\n\n/** Returns true if the provided package name is installed on the provided Android device. */\nexport async function isPackageInstalledAsync(\n device: DeviceContext,\n androidPackage: string\n): Promise<boolean> {\n const packages = await getServer().runAsync(\n adbArgs(\n device.pid,\n 'shell',\n 'pm',\n 'list',\n 'packages',\n '--user',\n env.EXPO_ADB_USER,\n androidPackage\n )\n );\n\n const lines = packages.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line === `package:${androidPackage}`) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.launchActivity Activity to launch `[application identifier]/.[main activity name]`, ex: `com.bacon.app/.MainActivity`\n * @param props.url Optional (dev client) URL to launch\n */\nexport async function launchActivityAsync(\n device: DeviceContext,\n {\n launchActivity,\n url,\n }: {\n launchActivity: string;\n url?: string;\n }\n) {\n const args: string[] = [\n 'shell',\n 'am',\n 'start',\n // FLAG_ACTIVITY_SINGLE_TOP -- If set, the activity will not be launched if it is already running at the top of the history stack.\n '-f',\n '0x20000000',\n // Activity to open first: com.bacon.app/.MainActivity\n '-n',\n launchActivity,\n ];\n\n if (url) {\n args.push('-d', url);\n }\n\n return openAsync(adbArgs(device.pid, ...args));\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.applicationId package name to launch.\n */\nexport async function openAppIdAsync(\n device: DeviceContext,\n {\n applicationId,\n }: {\n applicationId: string;\n }\n) {\n return openAsync(\n adbArgs(\n device.pid,\n 'shell',\n 'monkey',\n '-p',\n applicationId,\n '-c',\n 'android.intent.category.LAUNCHER',\n '1'\n )\n );\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.url URL to launch.\n */\nexport async function openUrlAsync(\n device: DeviceContext,\n {\n url,\n }: {\n url: string;\n }\n) {\n return openAsync(\n adbArgs(\n device.pid,\n 'shell',\n 'am',\n 'start',\n '-a',\n 'android.intent.action.VIEW',\n '-d',\n // ADB requires ampersands to be escaped.\n url.replace(/&/g, String.raw`\\&`)\n )\n );\n}\n\n/** Runs a generic command watches for common errors in order to throw with an expected code. */\nasync function openAsync(args: string[]): Promise<string> {\n const results = await getServer().runAsync(args);\n if (\n results.includes(CANT_START_ACTIVITY_ERROR) ||\n results.match(/Error: Activity class .* does not exist\\./g)\n ) {\n throw new CommandError('APP_NOT_INSTALLED', results.substring(results.indexOf('Error: ')));\n }\n return results;\n}\n\n/** Uninstall an app given its Android package name. */\nexport async function uninstallAsync(\n device: DeviceContext,\n { appId }: { appId: string }\n): Promise<string> {\n return await getServer().runAsync(\n adbArgs(device.pid, 'uninstall', '--user', env.EXPO_ADB_USER, appId)\n );\n}\n\n/** Get package info from an app based on its Android package name. */\nexport async function getPackageInfoAsync(\n device: DeviceContext,\n { appId }: { appId: string }\n): Promise<string> {\n return await getServer().runAsync(adbArgs(device.pid, 'shell', 'dumpsys', 'package', appId));\n}\n\n/** Install an app on a connected device. */\nexport async function installAsync(device: DeviceContext, { filePath }: { filePath: string }) {\n // TODO: Handle the `INSTALL_FAILED_INSUFFICIENT_STORAGE` error.\n return await getServer().runAsync(\n adbArgs(device.pid, 'install', '-r', '-d', '--user', env.EXPO_ADB_USER, filePath)\n );\n}\n\n/** Format ADB args with process ID. */\nexport function adbArgs(pid: Device['pid'], ...options: string[]): string[] {\n const args = [];\n if (pid) {\n args.push('-s', pid);\n }\n\n return args.concat(options);\n}\n\n// TODO: This is very expensive for some operations.\nexport async function getAttachedDevicesAsync(): Promise<Device[]> {\n const output = await getServer().runAsync(['devices', '-l']);\n\n const splitItems = output\n .trim()\n .replace(/\\n$/, '')\n .split(os.EOL)\n // Filter ADB trace logs from the output, e.g.\n // adb D 03-06 15:25:53 63677 4018815 adb_client.cpp:393] adb_query: host:devices-l\n // 03-04 12:29:44.557 16415 16415 D adb : commandline.cpp:1646 Using server socket: tcp:172.27.192.1:5037\n // 03-04 12:29:44.557 16415 16415 D adb : adb_client.cpp:160 _adb_connect: host:version\n .filter((line) => !line.match(/\\.cpp:[0-9]+/));\n\n // First line is `\"List of devices attached\"`, remove it\n // @ts-ignore: todo\n const attachedDevices: {\n props: string[];\n type: Device['type'];\n isAuthorized: Device['isAuthorized'];\n isBooted: Device['isBooted'];\n connectionType?: Device['connectionType'];\n }[] = splitItems\n .slice(1, splitItems.length)\n .map((line) => {\n // unauthorized: ['FA8251A00719', 'unauthorized', 'usb:338690048X', 'transport_id:5']\n // authorized: ['FA8251A00719', 'device', 'usb:336592896X', 'product:walleye', 'model:Pixel_2', 'device:walleye', 'transport_id:4']\n // emulator: ['emulator-5554', 'offline', 'transport_id:1']\n const props = line.split(' ').filter(Boolean);\n const type = line.includes('emulator') ? 'emulator' : 'device';\n\n let connectionType;\n if (type === 'device' && line.includes('usb:')) {\n connectionType = 'USB';\n } else if (type === 'device' && line.includes('_adb-tls-connect.')) {\n connectionType = 'Network';\n }\n\n const isBooted = type === 'emulator' || props[1] !== 'offline';\n const isAuthorized =\n connectionType === 'Network'\n ? line.includes('model:') // Network connected devices show `model:<name>` when authorized\n : props[1] !== 'unauthorized';\n\n return { props, type, isAuthorized, isBooted, connectionType };\n })\n .filter(({ props: [pid] }) => !!pid);\n\n const devicePromises = attachedDevices.map<Promise<Device>>(async (props) => {\n const {\n type,\n props: [pid, ...deviceInfo],\n isAuthorized,\n isBooted,\n } = props;\n\n let name: string | null = null;\n\n if (type === 'device') {\n if (isAuthorized) {\n // Possibly formatted like `model:Pixel_2`\n // Transform to `Pixel_2`\n const modelItem = deviceInfo.find((info) => info.includes('model:'));\n if (modelItem) {\n name = modelItem.replace('model:', '');\n }\n }\n // unauthorized devices don't have a name available to read\n if (!name) {\n // Device FA8251A00719\n name = `Device ${pid}`;\n }\n } else {\n // Given an emulator pid, get the emulator name which can be used to start the emulator later.\n name = (await getAdbNameForDeviceIdAsync({ pid })) ?? '';\n }\n\n return props.connectionType\n ? { pid, name, type, isAuthorized, isBooted, connectionType: props.connectionType }\n : { pid, name, type, isAuthorized, isBooted };\n });\n\n return Promise.all(devicePromises);\n}\n\n/**\n * Return the Emulator name for an emulator ID, this can be used to determine if an emulator is booted.\n *\n * @param device.pid a value like `emulator-5554` from `abd devices`\n */\nexport async function getAdbNameForDeviceIdAsync(device: DeviceContext): Promise<string | null> {\n const results = await getServer().runAsync(adbArgs(device.pid, 'emu', 'avd', 'name'));\n\n if (results.match(/could not connect to TCP port .*: Connection refused/)) {\n // Can also occur when the emulator does not exist.\n throw new CommandError('EMULATOR_NOT_FOUND', results);\n }\n\n return sanitizeAdbDeviceName(results) ?? null;\n}\n\nexport async function isDeviceBootedAsync({\n name,\n}: { name?: string } = {}): Promise<Device | null> {\n const devices = await getAttachedDevicesAsync();\n\n if (!name) {\n return devices[0] ?? null;\n }\n\n return devices.find((device) => device.name === name) ?? null;\n}\n\n/**\n * Returns true when a device's splash screen animation has stopped.\n * This can be used to detect when a device is fully booted and ready to use.\n *\n * @param pid\n */\nexport async function isBootAnimationCompleteAsync(pid?: string): Promise<boolean> {\n try {\n const props = await getPropertyDataForDeviceAsync({ pid }, PROP_BOOT_ANIMATION_STATE);\n return !!props[PROP_BOOT_ANIMATION_STATE].match(/stopped/);\n } catch {\n return false;\n }\n}\n\n/** Get a list of ABIs for the provided device. */\nexport async function getDeviceABIsAsync(\n device: Pick<Device, 'name' | 'pid'>\n): Promise<DeviceABI[]> {\n const cpuAbiList = (await getPropertyDataForDeviceAsync(device, PROP_CPU_ABI_LIST_NAME))[\n PROP_CPU_ABI_LIST_NAME\n ];\n\n if (cpuAbiList) {\n return cpuAbiList.trim().split(',') as DeviceABI[];\n }\n\n const abi = (await getPropertyDataForDeviceAsync(device, PROP_CPU_NAME))[\n PROP_CPU_NAME\n ] as DeviceABI;\n return [abi];\n}\n\nexport async function getPropertyDataForDeviceAsync(\n device: DeviceContext,\n prop?: string\n): Promise<DeviceProperties> {\n // @ts-ignore\n const propCommand = adbArgs(...[device.pid, 'shell', 'getprop', prop].filter(Boolean));\n try {\n // Prevent reading as UTF8.\n const results = await getServer().getFileOutputAsync(propCommand);\n // Like:\n // [wifi.direct.interface]: [p2p-dev-wlan0]\n // [wifi.interface]: [wlan0]\n\n if (prop) {\n debug(`Property data: (device pid: ${device.pid}, prop: ${prop}, data: ${results})`);\n return {\n [prop]: results,\n };\n }\n const props = parseAdbDeviceProperties(results);\n\n debug(`Parsed data:`, props);\n\n return props;\n } catch (error: any) {\n // TODO: Ensure error has message and not stderr\n throw new CommandError(`Failed to get properties for device (${device.pid}): ${error.message}`);\n }\n}\n\nfunction parseAdbDeviceProperties(devicePropertiesString: string) {\n const properties: DeviceProperties = {};\n const propertyExp = /\\[(.*?)\\]: \\[(.*?)\\]/gm;\n for (const match of devicePropertiesString.matchAll(propertyExp)) {\n properties[match[1]] = match[2];\n }\n return properties;\n}\n\n/**\n * Sanitize the ADB device name to only get the actual device name.\n * On Windows, we need to do \\r, \\n, and \\r\\n filtering to get the name.\n */\nexport function sanitizeAdbDeviceName(deviceName: string) {\n return deviceName\n .trim()\n .split(/[\\r\\n]+/)\n .shift();\n}\n"],"names":["DeviceABI","adbArgs","getAdbNameForDeviceIdAsync","getAttachedDevicesAsync","getDeviceABIsAsync","getPackageInfoAsync","getPropertyDataForDeviceAsync","getServer","installAsync","isBootAnimationCompleteAsync","isDeviceBootedAsync","isPackageInstalledAsync","launchActivityAsync","logUnauthorized","openAppIdAsync","openUrlAsync","sanitizeAdbDeviceName","uninstallAsync","debug","require","CANT_START_ACTIVITY_ERROR","PROP_CPU_NAME","PROP_CPU_ABI_LIST_NAME","PROP_BOOT_ANIMATION_STATE","_server","ADBServer","device","Log","warn","chalk","bold","name","dim","learnMore","androidPackage","packages","runAsync","pid","env","EXPO_ADB_USER","lines","split","i","length","line","trim","launchActivity","url","args","push","openAsync","applicationId","replace","String","raw","results","includes","match","CommandError","substring","indexOf","appId","filePath","options","concat","output","splitItems","os","EOL","filter","attachedDevices","slice","map","props","Boolean","type","connectionType","isBooted","isAuthorized","devicePromises","deviceInfo","modelItem","find","info","Promise","all","devices","cpuAbiList","abi","prop","propCommand","getFileOutputAsync","parseAdbDeviceProperties","error","message","devicePropertiesString","properties","propertyExp","matchAll","deviceName","shift"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/platforms/android/adb.ts"],"sourcesContent":["import chalk from 'chalk';\nimport os from 'os';\n\nimport { ADBServer } from './ADBServer';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\nimport { learnMore } from '../../../utils/link';\n\nconst debug = require('debug')('expo:start:platforms:android:adb') as typeof console.log;\n\nexport enum DeviceABI {\n // The arch specific android target platforms are soft-deprecated.\n // Instead of using TargetPlatform as a combination arch + platform\n // the code will be updated to carry arch information in [DarwinArch]\n // and [AndroidArch].\n arm = 'arm',\n arm64 = 'arm64',\n x64 = 'x64',\n x86 = 'x86',\n x8664 = 'x86_64',\n arm64v8a = 'arm64-v8a',\n armeabiV7a = 'armeabi-v7a',\n armeabi = 'armeabi',\n universal = 'universal',\n}\n\n/** Represents a connected Android device. */\nexport type Device = {\n /** Process ID. */\n pid?: string;\n /** Name of the device, also used as the ID for opening devices. */\n name: string;\n /** Is emulator or connected device. */\n type: 'emulator' | 'device';\n /** Is the device booted (emulator). */\n isBooted: boolean;\n /** Is device authorized for developing. https://expo.fyi/authorize-android-device */\n isAuthorized: boolean;\n /** The connection type to ADB, only available when `type: device` */\n connectionType?: 'USB' | 'Network';\n};\n\ntype DeviceContext = Pick<Device, 'pid'>;\n\ntype DeviceProperties = Record<string, string>;\n\nconst CANT_START_ACTIVITY_ERROR = 'Activity not started, unable to resolve Intent';\n// http://developer.android.com/ndk/guides/abis.html\nconst PROP_CPU_NAME = 'ro.product.cpu.abi';\n\nconst PROP_CPU_ABI_LIST_NAME = 'ro.product.cpu.abilist';\n\n// Can sometimes be null\n// http://developer.android.com/ndk/guides/abis.html\nconst PROP_BOOT_ANIMATION_STATE = 'init.svc.bootanim';\n\nlet _server: ADBServer | null;\n\n/** Return the lazily loaded ADB server instance. */\nexport function getServer() {\n _server ??= new ADBServer();\n return _server;\n}\n\n/** Logs an FYI message about authorizing your device. */\nexport function logUnauthorized(device: Device) {\n Log.warn(\n `\\nThis computer is not authorized for developing on ${chalk.bold(device.name)}. ${chalk.dim(\n learnMore('https://expo.fyi/authorize-android-device')\n )}`\n );\n}\n\n/** Returns true if the provided package name is installed on the provided Android device. */\nexport async function isPackageInstalledAsync(\n device: DeviceContext,\n androidPackage: string\n): Promise<boolean> {\n const packages = await getServer().runAsync(\n adbShellArgs(device.pid, 'pm', 'list', 'packages', '--user', env.EXPO_ADB_USER, androidPackage)\n );\n\n const lines = packages.split(/\\r?\\n/);\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i].trim();\n if (line === `package:${androidPackage}`) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.launchActivity Activity to launch `[application identifier]/.[main activity name]`, ex: `com.bacon.app/.MainActivity`\n * @param props.url Optional (dev client) URL to launch\n */\nexport async function launchActivityAsync(\n device: DeviceContext,\n {\n launchActivity,\n url,\n }: {\n launchActivity: string;\n url?: string;\n }\n) {\n const command: string[] = [\n 'am',\n 'start',\n // FLAG_ACTIVITY_SINGLE_TOP -- If set, the activity will not be launched if it is already running at the top of the history stack.\n '-f',\n '0x20000000',\n // Activity to open first: com.bacon.app/.MainActivity\n '-n',\n launchActivity,\n ];\n\n if (url) {\n command.push('-d', url);\n }\n\n return openAsync(adbShellArgs(device.pid, ...command));\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.applicationId package name to launch.\n */\nexport async function openAppIdAsync(\n device: DeviceContext,\n {\n applicationId,\n }: {\n applicationId: string;\n }\n) {\n return openAsync(\n adbArgs(\n device.pid,\n 'shell',\n 'monkey',\n '-p',\n applicationId,\n '-c',\n 'android.intent.category.LAUNCHER',\n '1'\n )\n );\n}\n\n/**\n * @param device.pid Process ID of the Android device to launch.\n * @param props.url URL to launch.\n */\nexport async function openUrlAsync(\n device: DeviceContext,\n {\n url,\n }: {\n url: string;\n }\n) {\n return openAsync(\n adbShellArgs(device.pid, 'am', 'start', '-a', 'android.intent.action.VIEW', '-d', url)\n );\n}\n\n/** Runs a generic command watches for common errors in order to throw with an expected code. */\nasync function openAsync(args: string[]): Promise<string> {\n const results = await getServer().runAsync(args);\n if (\n results.includes(CANT_START_ACTIVITY_ERROR) ||\n results.match(/Error: Activity class .* does not exist\\./g)\n ) {\n throw new CommandError('APP_NOT_INSTALLED', results.substring(results.indexOf('Error: ')));\n }\n return results;\n}\n\n/** Uninstall an app given its Android package name. */\nexport async function uninstallAsync(\n device: DeviceContext,\n { appId }: { appId: string }\n): Promise<string> {\n return await getServer().runAsync(\n adbArgs(device.pid, 'uninstall', '--user', env.EXPO_ADB_USER, appId)\n );\n}\n\n/** Get package info from an app based on its Android package name. */\nexport async function getPackageInfoAsync(\n device: DeviceContext,\n { appId }: { appId: string }\n): Promise<string> {\n return await getServer().runAsync(adbShellArgs(device.pid, 'dumpsys', 'package', appId));\n}\n\n/** Install an app on a connected device. */\nexport async function installAsync(device: DeviceContext, { filePath }: { filePath: string }) {\n // TODO: Handle the `INSTALL_FAILED_INSUFFICIENT_STORAGE` error.\n return await getServer().runAsync(\n adbArgs(device.pid, 'install', '-r', '-d', '--user', env.EXPO_ADB_USER, filePath)\n );\n}\n\n/** Format ADB args with process ID. */\nexport function adbArgs(pid: Device['pid'], ...options: string[]): string[] {\n const args = [];\n if (pid) {\n args.push('-s', pid);\n }\n\n return args.concat(options);\n}\n\n/**\n * `adb shell` concatenates trailing args and runs the result through `sh -c` on\n * the device, so unquoted metacharacters in tainted tokens execute on-device.\n */\nexport function adbShellArgs(pid: Device['pid'], ...command: string[]): string[] {\n return adbArgs(pid, 'shell', ...command.map(shellQuote));\n}\n\nfunction shellQuote(value: string): string {\n return `'${value.replace(/'/g, `'\\\\''`)}'`;\n}\n\n// TODO: This is very expensive for some operations.\nexport async function getAttachedDevicesAsync(): Promise<Device[]> {\n const output = await getServer().runAsync(['devices', '-l']);\n\n const splitItems = output\n .trim()\n .replace(/\\n$/, '')\n .split(os.EOL)\n // Filter ADB trace logs from the output, e.g.\n // adb D 03-06 15:25:53 63677 4018815 adb_client.cpp:393] adb_query: host:devices-l\n // 03-04 12:29:44.557 16415 16415 D adb : commandline.cpp:1646 Using server socket: tcp:172.27.192.1:5037\n // 03-04 12:29:44.557 16415 16415 D adb : adb_client.cpp:160 _adb_connect: host:version\n .filter((line) => !line.match(/\\.cpp:[0-9]+/));\n\n // First line is `\"List of devices attached\"`, remove it\n // @ts-ignore: todo\n const attachedDevices: {\n props: string[];\n type: Device['type'];\n isAuthorized: Device['isAuthorized'];\n isBooted: Device['isBooted'];\n connectionType?: Device['connectionType'];\n }[] = splitItems\n .slice(1, splitItems.length)\n .map((line) => {\n // unauthorized: ['FA8251A00719', 'unauthorized', 'usb:338690048X', 'transport_id:5']\n // authorized: ['FA8251A00719', 'device', 'usb:336592896X', 'product:walleye', 'model:Pixel_2', 'device:walleye', 'transport_id:4']\n // emulator: ['emulator-5554', 'offline', 'transport_id:1']\n const props = line.split(' ').filter(Boolean);\n const type = line.includes('emulator') ? 'emulator' : 'device';\n\n let connectionType;\n if (type === 'device' && line.includes('usb:')) {\n connectionType = 'USB';\n } else if (type === 'device' && line.includes('_adb-tls-connect.')) {\n connectionType = 'Network';\n }\n\n const isBooted = type === 'emulator' || props[1] !== 'offline';\n const isAuthorized =\n connectionType === 'Network'\n ? line.includes('model:') // Network connected devices show `model:<name>` when authorized\n : props[1] !== 'unauthorized';\n\n return { props, type, isAuthorized, isBooted, connectionType };\n })\n .filter(({ props: [pid] }) => !!pid);\n\n const devicePromises = attachedDevices.map<Promise<Device>>(async (props) => {\n const {\n type,\n props: [pid, ...deviceInfo],\n isAuthorized,\n isBooted,\n } = props;\n\n let name: string | null = null;\n\n if (type === 'device') {\n if (isAuthorized) {\n // Possibly formatted like `model:Pixel_2`\n // Transform to `Pixel_2`\n const modelItem = deviceInfo.find((info) => info.includes('model:'));\n if (modelItem) {\n name = modelItem.replace('model:', '');\n }\n }\n // unauthorized devices don't have a name available to read\n if (!name) {\n // Device FA8251A00719\n name = `Device ${pid}`;\n }\n } else {\n // Given an emulator pid, get the emulator name which can be used to start the emulator later.\n name = (await getAdbNameForDeviceIdAsync({ pid })) ?? '';\n }\n\n return props.connectionType\n ? { pid, name, type, isAuthorized, isBooted, connectionType: props.connectionType }\n : { pid, name, type, isAuthorized, isBooted };\n });\n\n return Promise.all(devicePromises);\n}\n\n/**\n * Return the Emulator name for an emulator ID, this can be used to determine if an emulator is booted.\n *\n * @param device.pid a value like `emulator-5554` from `abd devices`\n */\nexport async function getAdbNameForDeviceIdAsync(device: DeviceContext): Promise<string | null> {\n const results = await getServer().runAsync(adbArgs(device.pid, 'emu', 'avd', 'name'));\n\n if (results.match(/could not connect to TCP port .*: Connection refused/)) {\n // Can also occur when the emulator does not exist.\n throw new CommandError('EMULATOR_NOT_FOUND', results);\n }\n\n return sanitizeAdbDeviceName(results) ?? null;\n}\n\nexport async function isDeviceBootedAsync({\n name,\n}: { name?: string } = {}): Promise<Device | null> {\n const devices = await getAttachedDevicesAsync();\n\n if (!name) {\n return devices[0] ?? null;\n }\n\n return devices.find((device) => device.name === name) ?? null;\n}\n\n/**\n * Returns true when a device's splash screen animation has stopped.\n * This can be used to detect when a device is fully booted and ready to use.\n *\n * @param pid\n */\nexport async function isBootAnimationCompleteAsync(pid?: string): Promise<boolean> {\n try {\n const props = await getPropertyDataForDeviceAsync({ pid }, PROP_BOOT_ANIMATION_STATE);\n return !!props[PROP_BOOT_ANIMATION_STATE].match(/stopped/);\n } catch {\n return false;\n }\n}\n\n/** Get a list of ABIs for the provided device. */\nexport async function getDeviceABIsAsync(\n device: Pick<Device, 'name' | 'pid'>\n): Promise<DeviceABI[]> {\n const cpuAbiList = (await getPropertyDataForDeviceAsync(device, PROP_CPU_ABI_LIST_NAME))[\n PROP_CPU_ABI_LIST_NAME\n ];\n\n if (cpuAbiList) {\n return cpuAbiList.trim().split(',') as DeviceABI[];\n }\n\n const abi = (await getPropertyDataForDeviceAsync(device, PROP_CPU_NAME))[\n PROP_CPU_NAME\n ] as DeviceABI;\n return [abi];\n}\n\nexport async function getPropertyDataForDeviceAsync(\n device: DeviceContext,\n prop?: string\n): Promise<DeviceProperties> {\n const propCommand = prop\n ? adbShellArgs(device.pid, 'getprop', prop)\n : adbShellArgs(device.pid, 'getprop');\n try {\n // Prevent reading as UTF8.\n const results = await getServer().getFileOutputAsync(propCommand);\n // Like:\n // [wifi.direct.interface]: [p2p-dev-wlan0]\n // [wifi.interface]: [wlan0]\n\n if (prop) {\n debug(`Property data: (device pid: ${device.pid}, prop: ${prop}, data: ${results})`);\n return {\n [prop]: results,\n };\n }\n const props = parseAdbDeviceProperties(results);\n\n debug(`Parsed data:`, props);\n\n return props;\n } catch (error: any) {\n // TODO: Ensure error has message and not stderr\n throw new CommandError(`Failed to get properties for device (${device.pid}): ${error.message}`);\n }\n}\n\nfunction parseAdbDeviceProperties(devicePropertiesString: string) {\n const properties: DeviceProperties = {};\n const propertyExp = /\\[(.*?)\\]: \\[(.*?)\\]/gm;\n for (const match of devicePropertiesString.matchAll(propertyExp)) {\n properties[match[1]] = match[2];\n }\n return properties;\n}\n\n/**\n * Sanitize the ADB device name to only get the actual device name.\n * On Windows, we need to do \\r, \\n, and \\r\\n filtering to get the name.\n */\nexport function sanitizeAdbDeviceName(deviceName: string) {\n return deviceName\n .trim()\n .split(/[\\r\\n]+/)\n .shift();\n}\n"],"names":["DeviceABI","adbArgs","adbShellArgs","getAdbNameForDeviceIdAsync","getAttachedDevicesAsync","getDeviceABIsAsync","getPackageInfoAsync","getPropertyDataForDeviceAsync","getServer","installAsync","isBootAnimationCompleteAsync","isDeviceBootedAsync","isPackageInstalledAsync","launchActivityAsync","logUnauthorized","openAppIdAsync","openUrlAsync","sanitizeAdbDeviceName","uninstallAsync","debug","require","CANT_START_ACTIVITY_ERROR","PROP_CPU_NAME","PROP_CPU_ABI_LIST_NAME","PROP_BOOT_ANIMATION_STATE","_server","ADBServer","device","Log","warn","chalk","bold","name","dim","learnMore","androidPackage","packages","runAsync","pid","env","EXPO_ADB_USER","lines","split","i","length","line","trim","launchActivity","url","command","push","openAsync","applicationId","args","results","includes","match","CommandError","substring","indexOf","appId","filePath","options","concat","map","shellQuote","value","replace","output","splitItems","os","EOL","filter","attachedDevices","slice","props","Boolean","type","connectionType","isBooted","isAuthorized","devicePromises","deviceInfo","modelItem","find","info","Promise","all","devices","cpuAbiList","abi","prop","propCommand","getFileOutputAsync","parseAdbDeviceProperties","error","message","devicePropertiesString","properties","propertyExp","matchAll","deviceName","shift"],"mappings":";;;;;;;;;;;IAWYA,SAAS;eAATA;;IAqMIC,OAAO;eAAPA;;IAaAC,YAAY;eAAZA;;IAkGMC,0BAA0B;eAA1BA;;IAzFAC,uBAAuB;eAAvBA;;IAgIAC,kBAAkB;eAAlBA;;IAtKAC,mBAAmB;eAAnBA;;IAuLAC,6BAA6B;eAA7BA;;IA3TNC,SAAS;eAATA;;IA4IMC,YAAY;eAAZA;;IAoJAC,4BAA4B;eAA5BA;;IAlBAC,mBAAmB;eAAnBA;;IA/PAC,uBAAuB;eAAvBA;;IAuBAC,mBAAmB;eAAnBA;;IAhCNC,eAAe;eAAfA;;IAgEMC,cAAc;eAAdA;;IA0BAC,YAAY;eAAZA;;IAuQNC,qBAAqB;eAArBA;;IA7OMC,cAAc;eAAdA;;;;gEAtLJ;;;;;;;gEACH;;;;;;2BAEW;6DACL;qBACD;wBACS;sBACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAE1B,MAAMC,QAAQC,QAAQ,SAAS;AAExB,IAAA,AAAKpB,mCAAAA;IACV,kEAAkE;IAClE,mEAAmE;IACnE,qEAAqE;IACrE,qBAAqB;;;;;;;;;;WAJXA;;AAoCZ,MAAMqB,4BAA4B;AAClC,oDAAoD;AACpD,MAAMC,gBAAgB;AAEtB,MAAMC,yBAAyB;AAE/B,wBAAwB;AACxB,oDAAoD;AACpD,MAAMC,4BAA4B;AAElC,IAAIC;AAGG,SAASjB;IACdiB,YAAY,IAAIC,oBAAS;IACzB,OAAOD;AACT;AAGO,SAASX,gBAAgBa,MAAc;IAC5CC,KAAIC,IAAI,CACN,CAAC,oDAAoD,EAAEC,gBAAK,CAACC,IAAI,CAACJ,OAAOK,IAAI,EAAE,EAAE,EAAEF,gBAAK,CAACG,GAAG,CAC1FC,IAAAA,eAAS,EAAC,+CACT;AAEP;AAGO,eAAetB,wBACpBe,MAAqB,EACrBQ,cAAsB;IAEtB,MAAMC,WAAW,MAAM5B,YAAY6B,QAAQ,CACzCnC,aAAayB,OAAOW,GAAG,EAAE,MAAM,QAAQ,YAAY,UAAUC,QAAG,CAACC,aAAa,EAAEL;IAGlF,MAAMM,QAAQL,SAASM,KAAK,CAAC;IAC7B,IAAK,IAAIC,IAAI,GAAGA,IAAIF,MAAMG,MAAM,EAAED,IAAK;QACrC,MAAME,OAAOJ,KAAK,CAACE,EAAE,CAACG,IAAI;QAC1B,IAAID,SAAS,CAAC,QAAQ,EAAEV,gBAAgB,EAAE;YACxC,OAAO;QACT;IACF;IACA,OAAO;AACT;AAOO,eAAetB,oBACpBc,MAAqB,EACrB,EACEoB,cAAc,EACdC,GAAG,EAIJ;IAED,MAAMC,UAAoB;QACxB;QACA;QACA,kIAAkI;QAClI;QACA;QACA,sDAAsD;QACtD;QACAF;KACD;IAED,IAAIC,KAAK;QACPC,QAAQC,IAAI,CAAC,MAAMF;IACrB;IAEA,OAAOG,UAAUjD,aAAayB,OAAOW,GAAG,KAAKW;AAC/C;AAMO,eAAelC,eACpBY,MAAqB,EACrB,EACEyB,aAAa,EAGd;IAED,OAAOD,UACLlD,QACE0B,OAAOW,GAAG,EACV,SACA,UACA,MACAc,eACA,MACA,oCACA;AAGN;AAMO,eAAepC,aACpBW,MAAqB,EACrB,EACEqB,GAAG,EAGJ;IAED,OAAOG,UACLjD,aAAayB,OAAOW,GAAG,EAAE,MAAM,SAAS,MAAM,8BAA8B,MAAMU;AAEtF;AAEA,8FAA8F,GAC9F,eAAeG,UAAUE,IAAc;IACrC,MAAMC,UAAU,MAAM9C,YAAY6B,QAAQ,CAACgB;IAC3C,IACEC,QAAQC,QAAQ,CAAClC,8BACjBiC,QAAQE,KAAK,CAAC,+CACd;QACA,MAAM,IAAIC,oBAAY,CAAC,qBAAqBH,QAAQI,SAAS,CAACJ,QAAQK,OAAO,CAAC;IAChF;IACA,OAAOL;AACT;AAGO,eAAepC,eACpBS,MAAqB,EACrB,EAAEiC,KAAK,EAAqB;IAE5B,OAAO,MAAMpD,YAAY6B,QAAQ,CAC/BpC,QAAQ0B,OAAOW,GAAG,EAAE,aAAa,UAAUC,QAAG,CAACC,aAAa,EAAEoB;AAElE;AAGO,eAAetD,oBACpBqB,MAAqB,EACrB,EAAEiC,KAAK,EAAqB;IAE5B,OAAO,MAAMpD,YAAY6B,QAAQ,CAACnC,aAAayB,OAAOW,GAAG,EAAE,WAAW,WAAWsB;AACnF;AAGO,eAAenD,aAAakB,MAAqB,EAAE,EAAEkC,QAAQ,EAAwB;IAC1F,gEAAgE;IAChE,OAAO,MAAMrD,YAAY6B,QAAQ,CAC/BpC,QAAQ0B,OAAOW,GAAG,EAAE,WAAW,MAAM,MAAM,UAAUC,QAAG,CAACC,aAAa,EAAEqB;AAE5E;AAGO,SAAS5D,QAAQqC,GAAkB,EAAE,GAAGwB,OAAiB;IAC9D,MAAMT,OAAO,EAAE;IACf,IAAIf,KAAK;QACPe,KAAKH,IAAI,CAAC,MAAMZ;IAClB;IAEA,OAAOe,KAAKU,MAAM,CAACD;AACrB;AAMO,SAAS5D,aAAaoC,GAAkB,EAAE,GAAGW,OAAiB;IACnE,OAAOhD,QAAQqC,KAAK,YAAYW,QAAQe,GAAG,CAACC;AAC9C;AAEA,SAASA,WAAWC,KAAa;IAC/B,OAAO,CAAC,CAAC,EAAEA,MAAMC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC5C;AAGO,eAAe/D;IACpB,MAAMgE,SAAS,MAAM5D,YAAY6B,QAAQ,CAAC;QAAC;QAAW;KAAK;IAE3D,MAAMgC,aAAaD,OAChBtB,IAAI,GACJqB,OAAO,CAAC,OAAO,IACfzB,KAAK,CAAC4B,aAAE,CAACC,GAAG,CACb,8CAA8C;IAC9C,mFAAmF;IACnF,6GAA6G;IAC7G,2FAA2F;KAC1FC,MAAM,CAAC,CAAC3B,OAAS,CAACA,KAAKW,KAAK,CAAC;IAEhC,wDAAwD;IACxD,mBAAmB;IACnB,MAAMiB,kBAMAJ,WACHK,KAAK,CAAC,GAAGL,WAAWzB,MAAM,EAC1BoB,GAAG,CAAC,CAACnB;QACJ,qFAAqF;QACrF,mIAAmI;QACnI,2DAA2D;QAC3D,MAAM8B,QAAQ9B,KAAKH,KAAK,CAAC,KAAK8B,MAAM,CAACI;QACrC,MAAMC,OAAOhC,KAAKU,QAAQ,CAAC,cAAc,aAAa;QAEtD,IAAIuB;QACJ,IAAID,SAAS,YAAYhC,KAAKU,QAAQ,CAAC,SAAS;YAC9CuB,iBAAiB;QACnB,OAAO,IAAID,SAAS,YAAYhC,KAAKU,QAAQ,CAAC,sBAAsB;YAClEuB,iBAAiB;QACnB;QAEA,MAAMC,WAAWF,SAAS,cAAcF,KAAK,CAAC,EAAE,KAAK;QACrD,MAAMK,eACJF,mBAAmB,YACfjC,KAAKU,QAAQ,CAAC,UAAU,gEAAgE;WACxFoB,KAAK,CAAC,EAAE,KAAK;QAEnB,OAAO;YAAEA;YAAOE;YAAMG;YAAcD;YAAUD;QAAe;IAC/D,GACCN,MAAM,CAAC,CAAC,EAAEG,OAAO,CAACrC,IAAI,EAAE,GAAK,CAAC,CAACA;IAElC,MAAM2C,iBAAiBR,gBAAgBT,GAAG,CAAkB,OAAOW;QACjE,MAAM,EACJE,IAAI,EACJF,OAAO,CAACrC,KAAK,GAAG4C,WAAW,EAC3BF,YAAY,EACZD,QAAQ,EACT,GAAGJ;QAEJ,IAAI3C,OAAsB;QAE1B,IAAI6C,SAAS,UAAU;YACrB,IAAIG,cAAc;gBAChB,0CAA0C;gBAC1C,yBAAyB;gBACzB,MAAMG,YAAYD,WAAWE,IAAI,CAAC,CAACC,OAASA,KAAK9B,QAAQ,CAAC;gBAC1D,IAAI4B,WAAW;oBACbnD,OAAOmD,UAAUhB,OAAO,CAAC,UAAU;gBACrC;YACF;YACA,2DAA2D;YAC3D,IAAI,CAACnC,MAAM;gBACT,sBAAsB;gBACtBA,OAAO,CAAC,OAAO,EAAEM,KAAK;YACxB;QACF,OAAO;YACL,8FAA8F;YAC9FN,OAAO,AAAC,MAAM7B,2BAA2B;gBAAEmC;YAAI,MAAO;QACxD;QAEA,OAAOqC,MAAMG,cAAc,GACvB;YAAExC;YAAKN;YAAM6C;YAAMG;YAAcD;YAAUD,gBAAgBH,MAAMG,cAAc;QAAC,IAChF;YAAExC;YAAKN;YAAM6C;YAAMG;YAAcD;QAAS;IAChD;IAEA,OAAOO,QAAQC,GAAG,CAACN;AACrB;AAOO,eAAe9E,2BAA2BwB,MAAqB;IACpE,MAAM2B,UAAU,MAAM9C,YAAY6B,QAAQ,CAACpC,QAAQ0B,OAAOW,GAAG,EAAE,OAAO,OAAO;IAE7E,IAAIgB,QAAQE,KAAK,CAAC,yDAAyD;QACzE,mDAAmD;QACnD,MAAM,IAAIC,oBAAY,CAAC,sBAAsBH;IAC/C;IAEA,OAAOrC,sBAAsBqC,YAAY;AAC3C;AAEO,eAAe3C,oBAAoB,EACxCqB,IAAI,EACc,GAAG,CAAC,CAAC;IACvB,MAAMwD,UAAU,MAAMpF;IAEtB,IAAI,CAAC4B,MAAM;QACT,OAAOwD,OAAO,CAAC,EAAE,IAAI;IACvB;IAEA,OAAOA,QAAQJ,IAAI,CAAC,CAACzD,SAAWA,OAAOK,IAAI,KAAKA,SAAS;AAC3D;AAQO,eAAetB,6BAA6B4B,GAAY;IAC7D,IAAI;QACF,MAAMqC,QAAQ,MAAMpE,8BAA8B;YAAE+B;QAAI,GAAGd;QAC3D,OAAO,CAAC,CAACmD,KAAK,CAACnD,0BAA0B,CAACgC,KAAK,CAAC;IAClD,EAAE,OAAM;QACN,OAAO;IACT;AACF;AAGO,eAAenD,mBACpBsB,MAAoC;IAEpC,MAAM8D,aAAa,AAAC,CAAA,MAAMlF,8BAA8BoB,QAAQJ,uBAAsB,CAAE,CACtFA,uBACD;IAED,IAAIkE,YAAY;QACd,OAAOA,WAAW3C,IAAI,GAAGJ,KAAK,CAAC;IACjC;IAEA,MAAMgD,MAAM,AAAC,CAAA,MAAMnF,8BAA8BoB,QAAQL,cAAa,CAAE,CACtEA,cACD;IACD,OAAO;QAACoE;KAAI;AACd;AAEO,eAAenF,8BACpBoB,MAAqB,EACrBgE,IAAa;IAEb,MAAMC,cAAcD,OAChBzF,aAAayB,OAAOW,GAAG,EAAE,WAAWqD,QACpCzF,aAAayB,OAAOW,GAAG,EAAE;IAC7B,IAAI;QACF,2BAA2B;QAC3B,MAAMgB,UAAU,MAAM9C,YAAYqF,kBAAkB,CAACD;QACrD,QAAQ;QACR,2CAA2C;QAC3C,4BAA4B;QAE5B,IAAID,MAAM;YACRxE,MAAM,CAAC,4BAA4B,EAAEQ,OAAOW,GAAG,CAAC,QAAQ,EAAEqD,KAAK,QAAQ,EAAErC,QAAQ,CAAC,CAAC;YACnF,OAAO;gBACL,CAACqC,KAAK,EAAErC;YACV;QACF;QACA,MAAMqB,QAAQmB,yBAAyBxC;QAEvCnC,MAAM,CAAC,YAAY,CAAC,EAAEwD;QAEtB,OAAOA;IACT,EAAE,OAAOoB,OAAY;QACnB,gDAAgD;QAChD,MAAM,IAAItC,oBAAY,CAAC,CAAC,qCAAqC,EAAE9B,OAAOW,GAAG,CAAC,GAAG,EAAEyD,MAAMC,OAAO,EAAE;IAChG;AACF;AAEA,SAASF,yBAAyBG,sBAA8B;IAC9D,MAAMC,aAA+B,CAAC;IACtC,MAAMC,cAAc;IACpB,KAAK,MAAM3C,SAASyC,uBAAuBG,QAAQ,CAACD,aAAc;QAChED,UAAU,CAAC1C,KAAK,CAAC,EAAE,CAAC,GAAGA,KAAK,CAAC,EAAE;IACjC;IACA,OAAO0C;AACT;AAMO,SAASjF,sBAAsBoF,UAAkB;IACtD,OAAOA,WACJvD,IAAI,GACJJ,KAAK,CAAC,WACN4D,KAAK;AACV"}