@expo/cli 54.0.24 → 54.0.26

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 (62) 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/resolveInstallApkName.js +48 -1
  17. package/build/src/run/android/resolveInstallApkName.js.map +1 -1
  18. package/build/src/run/android/resolveLaunchProps.js +4 -1
  19. package/build/src/run/android/resolveLaunchProps.js.map +1 -1
  20. package/build/src/run/ios/XcodeBuild.js +23 -0
  21. package/build/src/run/ios/XcodeBuild.js.map +1 -1
  22. package/build/src/run/ios/appleDevice/client/LockdowndClient.js +1 -1
  23. package/build/src/run/ios/appleDevice/client/LockdowndClient.js.map +1 -1
  24. package/build/src/start/platforms/android/adb.js +16 -15
  25. package/build/src/start/platforms/android/adb.js.map +1 -1
  26. package/build/src/start/server/DevToolsPluginManager.js.map +1 -1
  27. package/build/src/start/server/getStaticRenderFunctions.js +2 -1
  28. package/build/src/start/server/getStaticRenderFunctions.js.map +1 -1
  29. package/build/src/start/server/metro/debugging/createDebugMiddleware.js +6 -5
  30. package/build/src/start/server/metro/debugging/createDebugMiddleware.js.map +1 -1
  31. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js +17 -1
  32. package/build/src/start/server/metro/debugging/messageHandlers/NetworkResponse.js.map +1 -1
  33. package/build/src/start/server/metro/dev-server/createMessageSocket.js +13 -2
  34. package/build/src/start/server/metro/dev-server/createMessageSocket.js.map +1 -1
  35. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js +10 -3
  36. package/build/src/start/server/metro/dev-server/createMetroMiddleware.js.map +1 -1
  37. package/build/src/start/server/metro/instantiateMetro.js +7 -3
  38. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  39. package/build/src/start/server/metro/metroErrorInterface.js +5 -2
  40. package/build/src/start/server/metro/metroErrorInterface.js.map +1 -1
  41. package/build/src/start/server/metro/router.js +10 -1
  42. package/build/src/start/server/metro/router.js.map +1 -1
  43. package/build/src/start/server/middleware/InterstitialPageMiddleware.js +7 -4
  44. package/build/src/start/server/middleware/InterstitialPageMiddleware.js.map +1 -1
  45. package/build/src/start/server/middleware/ServeStaticMiddleware.js +2 -9
  46. package/build/src/start/server/middleware/ServeStaticMiddleware.js.map +1 -1
  47. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js +14 -24
  48. package/build/src/start/server/middleware/inspector/createJsInspectorMiddleware.js.map +1 -1
  49. package/build/src/start/server/webTemplate.js +3 -5
  50. package/build/src/start/server/webTemplate.js.map +1 -1
  51. package/build/src/utils/codesigning.js +6 -0
  52. package/build/src/utils/codesigning.js.map +1 -1
  53. package/build/src/utils/findUp.js +17 -19
  54. package/build/src/utils/findUp.js.map +1 -1
  55. package/build/src/utils/net.js +13 -0
  56. package/build/src/utils/net.js.map +1 -1
  57. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  58. package/build/src/utils/telemetry/utils/context.js +1 -1
  59. package/build/src/utils/url.js +0 -12
  60. package/build/src/utils/url.js.map +1 -1
  61. package/package.json +11 -11
  62. 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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"}
@@ -29,6 +29,52 @@ function _interop_require_default(obj) {
29
29
  };
30
30
  }
31
31
  const debug = require('debug')('expo:run:android:resolveInstallApkName');
32
+ function resolveApkFromOutputMetadata(apkVariantDirectory, availableCPUs) {
33
+ const metadataPath = _path().default.join(apkVariantDirectory, 'output-metadata.json');
34
+ let metadata;
35
+ try {
36
+ metadata = JSON.parse(_fs().default.readFileSync(metadataPath, 'utf8'));
37
+ } catch (error) {
38
+ debug('Failed to parse output-metadata.json', error);
39
+ return null;
40
+ }
41
+ const { elements } = metadata;
42
+ if (!(elements == null ? void 0 : elements.length)) {
43
+ return null;
44
+ }
45
+ // ABI split: match by device ABI. Exclude DeviceABI.universal — AGP never uses it as an ABI filter.
46
+ const isAbiSplit = elements.some((e)=>{
47
+ var _e_filters;
48
+ return e == null ? void 0 : (_e_filters = e.filters) == null ? void 0 : _e_filters.some((f)=>(f == null ? void 0 : f.filterType) === 'ABI');
49
+ });
50
+ if (isAbiSplit) {
51
+ for (const cpu of availableCPUs){
52
+ if (cpu === _adb.DeviceABI.universal) {
53
+ continue;
54
+ }
55
+ const match = elements.find((e)=>{
56
+ var _e_filters;
57
+ return e == null ? void 0 : (_e_filters = e.filters) == null ? void 0 : _e_filters.some((f)=>f.filterType === 'ABI' && f.value === cpu);
58
+ });
59
+ const outputFile = match == null ? void 0 : match.outputFile;
60
+ if (typeof outputFile === 'string' && _fs().default.existsSync(_path().default.join(apkVariantDirectory, outputFile))) {
61
+ debug('Resolved ABI-split APK from output-metadata.json:', outputFile);
62
+ return outputFile;
63
+ }
64
+ }
65
+ return null;
66
+ }
67
+ if (elements.length === 1) {
68
+ var _elements_;
69
+ const outputFile = (_elements_ = elements[0]) == null ? void 0 : _elements_.outputFile;
70
+ if (typeof outputFile === 'string' && _fs().default.existsSync(_path().default.join(apkVariantDirectory, outputFile))) {
71
+ debug('Resolved APK from output-metadata.json:', outputFile);
72
+ return outputFile;
73
+ }
74
+ }
75
+ // Density/language splits produce multiple elements without ABI filters
76
+ return null;
77
+ }
32
78
  async function resolveInstallApkNameAsync(device, { appName, buildType, flavors, apkVariantDirectory }) {
33
79
  const availableCPUs = await (0, _adb.getDeviceABIsAsync)(device);
34
80
  availableCPUs.push(_adb.DeviceABI.universal);
@@ -50,7 +96,8 @@ async function resolveInstallApkNameAsync(device, { appName, buildType, flavors,
50
96
  if (_fs().default.existsSync(apkPath)) {
51
97
  return apkName;
52
98
  }
53
- return null;
99
+ // Last resort: read AGP's output-metadata.json to handle custom outputFileName overrides.
100
+ return resolveApkFromOutputMetadata(apkVariantDirectory, availableCPUs);
54
101
  }
55
102
  function getApkFileName(appName, buildType, flavors, cpuArch) {
56
103
  let apkName = `${appName}-`;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/run/android/resolveInstallApkName.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { GradleProps } from './resolveGradlePropsAsync';\nimport { Device, DeviceABI, getDeviceABIsAsync } from '../../start/platforms/android/adb';\n\nconst debug = require('debug')('expo:run:android:resolveInstallApkName') as typeof console.log;\n\nexport async function resolveInstallApkNameAsync(\n device: Pick<Device, 'name' | 'pid'>,\n { appName, buildType, flavors, apkVariantDirectory }: GradleProps\n) {\n const availableCPUs = await getDeviceABIsAsync(device);\n availableCPUs.push(DeviceABI.universal);\n\n debug('Supported ABIs: ' + availableCPUs.join(', '));\n debug('Searching for APK: ' + apkVariantDirectory);\n\n // Check for cpu specific builds first\n for (const availableCPU of availableCPUs) {\n const apkName = getApkFileName(appName, buildType, flavors, availableCPU);\n const apkPath = path.join(apkVariantDirectory, apkName);\n debug('Checking for APK at:', apkPath);\n if (fs.existsSync(apkPath)) {\n return apkName;\n }\n }\n\n // Otherwise use the default apk named after the variant: app-debug.apk\n const apkName = getApkFileName(appName, buildType, flavors);\n const apkPath = path.join(apkVariantDirectory, apkName);\n debug('Checking for fallback APK at:', apkPath);\n if (fs.existsSync(apkPath)) {\n return apkName;\n }\n\n return null;\n}\n\nfunction getApkFileName(\n appName: string,\n buildType: string,\n flavors?: string[] | null,\n cpuArch?: string | null\n) {\n let apkName = `${appName}-`;\n if (flavors) {\n apkName += flavors.reduce((rest, flavor) => `${rest}${flavor}-`, '');\n }\n if (cpuArch) {\n apkName += `${cpuArch}-`;\n }\n apkName += `${buildType}.apk`;\n\n return apkName;\n}\n"],"names":["resolveInstallApkNameAsync","debug","require","device","appName","buildType","flavors","apkVariantDirectory","availableCPUs","getDeviceABIsAsync","push","DeviceABI","universal","join","availableCPU","apkName","getApkFileName","apkPath","path","fs","existsSync","cpuArch","reduce","rest","flavor"],"mappings":";;;;+BAQsBA;;;eAAAA;;;;gEARP;;;;;;;gEACE;;;;;;qBAGqC;;;;;;AAEtD,MAAMC,QAAQC,QAAQ,SAAS;AAExB,eAAeF,2BACpBG,MAAoC,EACpC,EAAEC,OAAO,EAAEC,SAAS,EAAEC,OAAO,EAAEC,mBAAmB,EAAe;IAEjE,MAAMC,gBAAgB,MAAMC,IAAAA,uBAAkB,EAACN;IAC/CK,cAAcE,IAAI,CAACC,cAAS,CAACC,SAAS;IAEtCX,MAAM,qBAAqBO,cAAcK,IAAI,CAAC;IAC9CZ,MAAM,wBAAwBM;IAE9B,sCAAsC;IACtC,KAAK,MAAMO,gBAAgBN,cAAe;QACxC,MAAMO,UAAUC,eAAeZ,SAASC,WAAWC,SAASQ;QAC5D,MAAMG,UAAUC,eAAI,CAACL,IAAI,CAACN,qBAAqBQ;QAC/Cd,MAAM,wBAAwBgB;QAC9B,IAAIE,aAAE,CAACC,UAAU,CAACH,UAAU;YAC1B,OAAOF;QACT;IACF;IAEA,uEAAuE;IACvE,MAAMA,UAAUC,eAAeZ,SAASC,WAAWC;IACnD,MAAMW,UAAUC,eAAI,CAACL,IAAI,CAACN,qBAAqBQ;IAC/Cd,MAAM,iCAAiCgB;IACvC,IAAIE,aAAE,CAACC,UAAU,CAACH,UAAU;QAC1B,OAAOF;IACT;IAEA,OAAO;AACT;AAEA,SAASC,eACPZ,OAAe,EACfC,SAAiB,EACjBC,OAAyB,EACzBe,OAAuB;IAEvB,IAAIN,UAAU,GAAGX,QAAQ,CAAC,CAAC;IAC3B,IAAIE,SAAS;QACXS,WAAWT,QAAQgB,MAAM,CAAC,CAACC,MAAMC,SAAW,GAAGD,OAAOC,OAAO,CAAC,CAAC,EAAE;IACnE;IACA,IAAIH,SAAS;QACXN,WAAW,GAAGM,QAAQ,CAAC,CAAC;IAC1B;IACAN,WAAW,GAAGV,UAAU,IAAI,CAAC;IAE7B,OAAOU;AACT"}
1
+ {"version":3,"sources":["../../../../src/run/android/resolveInstallApkName.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { GradleProps } from './resolveGradlePropsAsync';\nimport { Device, DeviceABI, getDeviceABIsAsync } from '../../start/platforms/android/adb';\n\nconst debug = require('debug')('expo:run:android:resolveInstallApkName') as typeof console.log;\n\ntype OutputMetadataElement = {\n filters?: { filterType: string; value: string }[];\n outputFile: string;\n};\n\ntype OutputMetadata = {\n elements: OutputMetadataElement[];\n};\n\nfunction resolveApkFromOutputMetadata(\n apkVariantDirectory: string,\n availableCPUs: DeviceABI[]\n): string | null {\n const metadataPath = path.join(apkVariantDirectory, 'output-metadata.json');\n let metadata: OutputMetadata;\n try {\n metadata = JSON.parse(fs.readFileSync(metadataPath, 'utf8'));\n } catch (error) {\n debug('Failed to parse output-metadata.json', error);\n return null;\n }\n\n const { elements } = metadata;\n if (!elements?.length) {\n return null;\n }\n\n // ABI split: match by device ABI. Exclude DeviceABI.universal — AGP never uses it as an ABI filter.\n const isAbiSplit = elements.some((e) => e?.filters?.some((f) => f?.filterType === 'ABI'));\n if (isAbiSplit) {\n for (const cpu of availableCPUs) {\n if (cpu === DeviceABI.universal) {\n continue;\n }\n const match = elements.find((e) =>\n e?.filters?.some((f) => f.filterType === 'ABI' && f.value === cpu)\n );\n const outputFile = match?.outputFile;\n if (\n typeof outputFile === 'string' &&\n fs.existsSync(path.join(apkVariantDirectory, outputFile))\n ) {\n debug('Resolved ABI-split APK from output-metadata.json:', outputFile);\n return outputFile;\n }\n }\n return null;\n }\n\n if (elements.length === 1) {\n const outputFile = elements[0]?.outputFile;\n if (\n typeof outputFile === 'string' &&\n fs.existsSync(path.join(apkVariantDirectory, outputFile))\n ) {\n debug('Resolved APK from output-metadata.json:', outputFile);\n return outputFile;\n }\n }\n\n // Density/language splits produce multiple elements without ABI filters\n return null;\n}\n\nexport async function resolveInstallApkNameAsync(\n device: Pick<Device, 'name' | 'pid'>,\n { appName, buildType, flavors, apkVariantDirectory }: GradleProps\n) {\n const availableCPUs = await getDeviceABIsAsync(device);\n availableCPUs.push(DeviceABI.universal);\n\n debug('Supported ABIs: ' + availableCPUs.join(', '));\n debug('Searching for APK: ' + apkVariantDirectory);\n\n // Check for cpu specific builds first\n for (const availableCPU of availableCPUs) {\n const apkName = getApkFileName(appName, buildType, flavors, availableCPU);\n const apkPath = path.join(apkVariantDirectory, apkName);\n debug('Checking for APK at:', apkPath);\n if (fs.existsSync(apkPath)) {\n return apkName;\n }\n }\n\n // Otherwise use the default apk named after the variant: app-debug.apk\n const apkName = getApkFileName(appName, buildType, flavors);\n const apkPath = path.join(apkVariantDirectory, apkName);\n debug('Checking for fallback APK at:', apkPath);\n if (fs.existsSync(apkPath)) {\n return apkName;\n }\n\n // Last resort: read AGP's output-metadata.json to handle custom outputFileName overrides.\n return resolveApkFromOutputMetadata(apkVariantDirectory, availableCPUs);\n}\n\nfunction getApkFileName(\n appName: string,\n buildType: string,\n flavors?: string[] | null,\n cpuArch?: string | null\n) {\n let apkName = `${appName}-`;\n if (flavors) {\n apkName += flavors.reduce((rest, flavor) => `${rest}${flavor}-`, '');\n }\n if (cpuArch) {\n apkName += `${cpuArch}-`;\n }\n apkName += `${buildType}.apk`;\n\n return apkName;\n}\n"],"names":["resolveInstallApkNameAsync","debug","require","resolveApkFromOutputMetadata","apkVariantDirectory","availableCPUs","metadataPath","path","join","metadata","JSON","parse","fs","readFileSync","error","elements","length","isAbiSplit","some","e","filters","f","filterType","cpu","DeviceABI","universal","match","find","value","outputFile","existsSync","device","appName","buildType","flavors","getDeviceABIsAsync","push","availableCPU","apkName","getApkFileName","apkPath","cpuArch","reduce","rest","flavor"],"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"}
@@ -12,6 +12,9 @@ _export(exports, {
12
12
  _assertXcodeBuildResults: function() {
13
13
  return _assertXcodeBuildResults;
14
14
  },
15
+ _extractXcodeBuildErrorLines: function() {
16
+ return _extractXcodeBuildErrorLines;
17
+ },
15
18
  buildAsync: function() {
16
19
  return buildAsync;
17
20
  },
@@ -360,10 +363,30 @@ function _assertXcodeBuildResults(code, results, error, xcodeProject, logFilePat
360
363
  if (localizedError) {
361
364
  throwWithMessage(_chalk().default.bold(localizedError) + '\n\n');
362
365
  }
366
+ // `@expo/xcpretty` can leave a real failure uncounted (its compile-error
367
+ // matching is stateful and anchored, and stderr never passes through it), so
368
+ // the build summary reads "0 error(s)" and in CI the full log below is
369
+ // truncated before the real error line.
370
+ const errorLines = _extractXcodeBuildErrorLines(results + '\n' + error);
371
+ if (errorLines.length) {
372
+ throwWithMessage(_chalk().default.red(errorLines.join('\n')) + '\n\n' + results + '\n\n' + error);
373
+ }
363
374
  // Show all the log info because often times the error is coming from a shell script,
364
375
  // that invoked a node script, that started metro, which threw an error.
365
376
  throwWithMessage(results + '\n\n' + error);
366
377
  }
378
+ function _extractXcodeBuildErrorLines(output) {
379
+ const seen = new Set();
380
+ const errors = [];
381
+ for (const raw of output.split(/\r?\n/)){
382
+ const line = raw.trim();
383
+ if (/(?:^|\s)error:\s/.test(line) && !seen.has(line)) {
384
+ seen.add(line);
385
+ errors.push(line);
386
+ }
387
+ }
388
+ return errors;
389
+ }
367
390
  function writeBuildLogs(projectRoot, buildOutput, errorOutput) {
368
391
  const [logFilePath, errorFilePath] = getErrorLogFilePath(projectRoot);
369
392
  _fs().default.writeFileSync(logFilePath, buildOutput);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/run/ios/XcodeBuild.ts"],"sourcesContent":["import { ExpoRunFormatter } from '@expo/xcpretty';\nimport chalk from 'chalk';\nimport { spawn, SpawnOptionsWithoutStdio } from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport { BuildProps, ProjectInfo } from './XcodeBuild.types';\nimport { ensureDeviceIsCodeSignedForDeploymentAsync } from './codeSigning/configureCodeSigning';\nimport { simulatorBuildRequiresCodeSigning } from './codeSigning/simulatorCodeSigning';\nimport * as Log from '../../log';\nimport { ensureDirectory } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { AbortCommandError, CommandError } from '../../utils/errors';\nimport { getUserTerminal } from '../../utils/terminal';\nexport function logPrettyItem(message: string) {\n Log.log(chalk`{whiteBright \\u203A} ${message}`);\n}\n\nexport function matchEstimatedBinaryPath(buildOutput: string): string | null {\n // Match the full path that contains `/(.*)/Developer/Xcode/DerivedData/(.*)/Build/Products/(.*)/(.*).app`\n const appBinaryPathMatch = buildOutput.match(\n /(\\/(?:\\\\\\s|[^ ])+\\/Developer\\/Xcode\\/DerivedData\\/(?:\\\\\\s|[^ ])+\\/Build\\/Products\\/(?:Debug|Release)-(?:[^\\s/]+)\\/(?:\\\\\\s|[^ ])+\\.app)/\n );\n if (!appBinaryPathMatch?.length) {\n throw new CommandError(\n 'XCODE_BUILD',\n `Malformed xcodebuild results: app binary path was not generated in build output. Report this issue and run your project with Xcode instead.`\n );\n } else {\n // Sort for the shortest\n const shortestPath = (appBinaryPathMatch.filter((a) => typeof a === 'string' && a) as string[])\n .sort((a: string, b: string) => a.length - b.length)[0]\n .trim();\n\n Log.debug(`Found app binary path: ${shortestPath}`);\n return shortestPath;\n }\n}\n/**\n *\n * @returns '/Users/evanbacon/Library/Developer/Xcode/DerivedData/myapp-gpgjqjodrxtervaufttwnsgimhrx/Build/Products/Debug-iphonesimulator/myapp.app'\n */\nexport function getAppBinaryPath(buildOutput: string) {\n // Matches what's used in \"Bundle React Native code and images\" script.\n // Requires that `-hideShellScriptEnvironment` is not included in the build command (extra logs).\n\n try {\n // Like `\\=/Users/evanbacon/Library/Developer/Xcode/DerivedData/Exponent-anpuosnglkxokahjhfszejloqfvo/Build/Products/Debug-iphonesimulator`\n const CONFIGURATION_BUILD_DIR = extractEnvVariableFromBuild(\n buildOutput,\n 'CONFIGURATION_BUILD_DIR'\n ).sort(\n // Longer name means more suffixes, we want the shortest possible one to be first.\n // Massive projects (like Expo Go) can sometimes print multiple different sets of environment variables.\n // This can become an issue with some\n (a, b) => a.length - b.length\n );\n // Like `Exponent.app`\n const UNLOCALIZED_RESOURCES_FOLDER_PATH = extractEnvVariableFromBuild(\n buildOutput,\n 'UNLOCALIZED_RESOURCES_FOLDER_PATH'\n );\n\n const binaryPath = path.join(\n // Use the shortest defined env variable (usually there's just one).\n CONFIGURATION_BUILD_DIR[0],\n // Use the last defined env variable.\n UNLOCALIZED_RESOURCES_FOLDER_PATH[UNLOCALIZED_RESOURCES_FOLDER_PATH.length - 1]\n );\n\n // If the app has a space in the name it'll fail because it isn't escaped properly by Xcode.\n return getEscapedPath(binaryPath);\n } catch (error) {\n if (error instanceof CommandError && error.code === 'XCODE_BUILD') {\n const possiblePath = matchEstimatedBinaryPath(buildOutput);\n if (possiblePath) {\n return possiblePath;\n }\n }\n throw error;\n }\n}\n\nexport function getEscapedPath(filePath: string): string {\n if (fs.existsSync(filePath)) {\n return filePath;\n }\n const unescapedPath = filePath.split(/\\\\ /).join(' ');\n if (fs.existsSync(unescapedPath)) {\n return unescapedPath;\n }\n throw new CommandError(\n 'XCODE_BUILD',\n `Unexpected: Generated app at path \"${filePath}\" cannot be read, the app cannot be installed. Report this and build onto a simulator.`\n );\n}\n\nexport function extractEnvVariableFromBuild(buildOutput: string, variableName: string) {\n // Xcode can sometimes escape `=` with a backslash or put the value in quotes\n const reg = new RegExp(`export ${variableName}\\\\\\\\?=(.*)$`, 'mg');\n const matched = [...buildOutput.matchAll(reg)];\n\n if (!matched || !matched.length) {\n throw new CommandError(\n 'XCODE_BUILD',\n `Malformed xcodebuild results: \"${variableName}\" variable was not generated in build output. Report this issue and run your project with Xcode instead.`\n );\n }\n return matched.map((value) => value[1]).filter(Boolean) as string[];\n}\n\nexport function getProcessOptions({\n packager,\n shouldSkipInitialBundling,\n terminal,\n port,\n eagerBundleOptions,\n}: {\n packager: boolean;\n shouldSkipInitialBundling?: boolean;\n terminal: string | undefined;\n port: number;\n eagerBundleOptions?: string;\n}): SpawnOptionsWithoutStdio {\n const SKIP_BUNDLING = shouldSkipInitialBundling ? '1' : undefined;\n if (packager) {\n return {\n env: {\n ...process.env,\n RCT_TERMINAL: terminal,\n SKIP_BUNDLING,\n RCT_METRO_PORT: port.toString(),\n __EXPO_EAGER_BUNDLE_OPTIONS: eagerBundleOptions,\n },\n };\n }\n\n return {\n env: {\n ...process.env,\n RCT_TERMINAL: terminal,\n SKIP_BUNDLING,\n __EXPO_EAGER_BUNDLE_OPTIONS: eagerBundleOptions,\n // Always skip launching the packager from a build script.\n // The script is used for people building their project directly from Xcode.\n // This essentially means \"› Running script 'Start Packager'\" does nothing.\n RCT_NO_LAUNCH_PACKAGER: 'true',\n // FORCE_BUNDLING: '0'\n },\n };\n}\n\nexport async function getXcodeBuildArgsAsync(\n props: Pick<\n BuildProps,\n | 'buildCache'\n | 'projectRoot'\n | 'xcodeProject'\n | 'configuration'\n | 'scheme'\n | 'device'\n | 'isSimulator'\n >\n): Promise<string[]> {\n const args = [\n props.xcodeProject.isWorkspace ? '-workspace' : '-project',\n props.xcodeProject.name,\n '-configuration',\n props.configuration,\n '-scheme',\n props.scheme,\n '-destination',\n `id=${props.device.udid}`,\n ];\n\n if (!props.isSimulator || simulatorBuildRequiresCodeSigning(props.projectRoot)) {\n const developmentTeamId = await ensureDeviceIsCodeSignedForDeploymentAsync(props.projectRoot);\n if (developmentTeamId) {\n args.push(\n `DEVELOPMENT_TEAM=${developmentTeamId}`,\n '-allowProvisioningUpdates',\n '-allowProvisioningDeviceRegistration'\n );\n }\n }\n\n // Add last\n if (props.buildCache === false) {\n args.push(\n // Will first clean the derived data folder.\n 'clean',\n // Then build step must be added otherwise the process will simply clean and exit.\n 'build'\n );\n }\n return args;\n}\n\nfunction spawnXcodeBuild(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { onData }: { onData: (data: string) => void }\n): Promise<{ code: number | null; results: string; error: string }> {\n const buildProcess = spawn('xcodebuild', args, options);\n\n let results = '';\n let error = '';\n\n buildProcess.stdout.on('data', (data: Buffer) => {\n const stringData = data.toString();\n results += stringData;\n onData(stringData);\n });\n\n buildProcess.stderr.on('data', (data: Buffer) => {\n const stringData = data instanceof Buffer ? data.toString() : data;\n error += stringData;\n });\n\n return new Promise(async (resolve, reject) => {\n buildProcess.on('close', (code: number) => {\n resolve({ code, results, error });\n });\n });\n}\n\nasync function spawnXcodeBuildWithFlush(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { onFlush }: { onFlush: (data: string) => void }\n): Promise<{ code: number | null; results: string; error: string }> {\n let currentBuffer = '';\n\n // Data can be sent in chunks that would have no relevance to our regex\n // this can cause massive slowdowns, so we need to ensure the data is complete before attempting to parse it.\n function flushBuffer() {\n if (!currentBuffer) {\n return;\n }\n\n const data = currentBuffer;\n // Reset buffer.\n currentBuffer = '';\n // Process data.\n onFlush(data);\n }\n\n const data = await spawnXcodeBuild(args, options, {\n onData(stringData) {\n currentBuffer += stringData;\n // Only flush the data if we have a full line.\n if (currentBuffer.endsWith(os.EOL)) {\n flushBuffer();\n }\n },\n });\n\n // Flush log data at the end just in case we missed something.\n flushBuffer();\n return data;\n}\n\nasync function spawnXcodeBuildWithFormat(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { projectRoot, xcodeProject }: { projectRoot: string; xcodeProject: ProjectInfo }\n): Promise<{ code: number | null; results: string; error: string; formatter: ExpoRunFormatter }> {\n Log.debug(` xcodebuild ${args.join(' ')}`);\n\n logPrettyItem(chalk.bold`Planning build`);\n\n const formatter = ExpoRunFormatter.create(projectRoot, {\n xcodeProject,\n isDebug: env.EXPO_DEBUG,\n });\n\n const results = await spawnXcodeBuildWithFlush(args, options, {\n onFlush(data) {\n // Process data.\n for (const line of formatter.pipe(data)) {\n // Log parsed results.\n Log.log(line);\n }\n },\n });\n\n Log.debug(`Exited with code: ${results.code}`);\n\n if (\n // User cancelled with ctrl-c\n results.code === null ||\n // Build interrupted\n results.code === 75\n ) {\n throw new AbortCommandError();\n }\n\n Log.log(formatter.getBuildSummary());\n\n return { ...results, formatter };\n}\n\nexport async function buildAsync(props: BuildProps): Promise<string> {\n const args = await getXcodeBuildArgsAsync(props);\n\n const { projectRoot, xcodeProject, shouldSkipInitialBundling, port, eagerBundleOptions } = props;\n\n const { code, results, formatter, error } = await spawnXcodeBuildWithFormat(\n args,\n getProcessOptions({\n packager: false,\n terminal: getUserTerminal(),\n shouldSkipInitialBundling,\n port,\n eagerBundleOptions,\n }),\n {\n projectRoot,\n xcodeProject,\n }\n );\n\n const logFilePath = writeBuildLogs(projectRoot, results, error);\n\n if (code !== 0) {\n // Determine if the logger found any errors;\n const wasErrorPresented = !!formatter.errors.length;\n\n if (wasErrorPresented) {\n // This has a flaw, if the user is missing a file, and there is a script error, only the missing file error will be shown.\n // They will only see the script error if they fix the missing file and rerun.\n // The flaw can be fixed by catching script errors in the custom logger.\n throw new CommandError(\n `Failed to build iOS project. \"xcodebuild\" exited with error code ${code}.`\n );\n }\n\n _assertXcodeBuildResults(code, results, error, xcodeProject, logFilePath);\n }\n return results;\n}\n\n// Exposed for testing.\nexport function _assertXcodeBuildResults(\n code: number | null,\n results: string,\n error: string,\n xcodeProject: { name: string },\n logFilePath: string\n): void {\n const errorTitle = `Failed to build iOS project. \"xcodebuild\" exited with error code ${code}.`;\n\n const throwWithMessage = (message: string): never => {\n throw new CommandError(\n `${errorTitle}\\nTo view more error logs, try building the app with Xcode directly, by opening ${xcodeProject.name}.\\n\\n` +\n message +\n `Build logs written to ${chalk.underline(logFilePath)}`\n );\n };\n\n const localizedError = error.match(/NSLocalizedFailure = \"(.*)\"/)?.[1];\n\n if (localizedError) {\n throwWithMessage(chalk.bold(localizedError) + '\\n\\n');\n }\n // Show all the log info because often times the error is coming from a shell script,\n // that invoked a node script, that started metro, which threw an error.\n\n throwWithMessage(results + '\\n\\n' + error);\n}\n\nfunction writeBuildLogs(projectRoot: string, buildOutput: string, errorOutput: string) {\n const [logFilePath, errorFilePath] = getErrorLogFilePath(projectRoot);\n\n fs.writeFileSync(logFilePath, buildOutput);\n fs.writeFileSync(errorFilePath, errorOutput);\n return logFilePath;\n}\n\nfunction getErrorLogFilePath(projectRoot: string): [string, string] {\n const folder = path.join(projectRoot, '.expo');\n ensureDirectory(folder);\n return [path.join(folder, 'xcodebuild.log'), path.join(folder, 'xcodebuild-error.log')];\n}\n"],"names":["_assertXcodeBuildResults","buildAsync","extractEnvVariableFromBuild","getAppBinaryPath","getEscapedPath","getProcessOptions","getXcodeBuildArgsAsync","logPrettyItem","matchEstimatedBinaryPath","message","Log","log","chalk","buildOutput","appBinaryPathMatch","match","length","CommandError","shortestPath","filter","a","sort","b","trim","debug","CONFIGURATION_BUILD_DIR","UNLOCALIZED_RESOURCES_FOLDER_PATH","binaryPath","path","join","error","code","possiblePath","filePath","fs","existsSync","unescapedPath","split","variableName","reg","RegExp","matched","matchAll","map","value","Boolean","packager","shouldSkipInitialBundling","terminal","port","eagerBundleOptions","SKIP_BUNDLING","undefined","env","process","RCT_TERMINAL","RCT_METRO_PORT","toString","__EXPO_EAGER_BUNDLE_OPTIONS","RCT_NO_LAUNCH_PACKAGER","props","args","xcodeProject","isWorkspace","name","configuration","scheme","device","udid","isSimulator","simulatorBuildRequiresCodeSigning","projectRoot","developmentTeamId","ensureDeviceIsCodeSignedForDeploymentAsync","push","buildCache","spawnXcodeBuild","options","onData","buildProcess","spawn","results","stdout","on","data","stringData","stderr","Buffer","Promise","resolve","reject","spawnXcodeBuildWithFlush","onFlush","currentBuffer","flushBuffer","endsWith","os","EOL","spawnXcodeBuildWithFormat","bold","formatter","ExpoRunFormatter","create","isDebug","EXPO_DEBUG","line","pipe","AbortCommandError","getBuildSummary","getUserTerminal","logFilePath","writeBuildLogs","wasErrorPresented","errors","errorTitle","throwWithMessage","underline","localizedError","errorOutput","errorFilePath","getErrorLogFilePath","writeFileSync","folder","ensureDirectory"],"mappings":";;;;;;;;;;;IAwVgBA,wBAAwB;eAAxBA;;IAzCMC,UAAU;eAAVA;;IA7MNC,2BAA2B;eAA3BA;;IAvDAC,gBAAgB;eAAhBA;;IAyCAC,cAAc;eAAdA;;IA4BAC,iBAAiB;eAAjBA;;IAyCMC,sBAAsB;eAAtBA;;IA1INC,aAAa;eAAbA;;IAIAC,wBAAwB;eAAxBA;;;;yBAnBiB;;;;;;;gEACf;;;;;;;yBAC8B;;;;;;;gEACjC;;;;;;;gEACA;;;;;;;gEACE;;;;;;sCAG0C;sCACT;6DAC7B;qBACW;qBACZ;wBAC4B;0BAChB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACzB,SAASD,cAAcE,OAAe;IAC3CC,KAAIC,GAAG,CAACC,IAAAA,gBAAK,CAAA,CAAC,qBAAqB,EAAEH,QAAQ,CAAC;AAChD;AAEO,SAASD,yBAAyBK,WAAmB;IAC1D,0GAA0G;IAC1G,MAAMC,qBAAqBD,YAAYE,KAAK,CAC1C;IAEF,IAAI,EAACD,sCAAAA,mBAAoBE,MAAM,GAAE;QAC/B,MAAM,IAAIC,oBAAY,CACpB,eACA,CAAC,2IAA2I,CAAC;IAEjJ,OAAO;QACL,wBAAwB;QACxB,MAAMC,eAAe,AAACJ,mBAAmBK,MAAM,CAAC,CAACC,IAAM,OAAOA,MAAM,YAAYA,GAC7EC,IAAI,CAAC,CAACD,GAAWE,IAAcF,EAAEJ,MAAM,GAAGM,EAAEN,MAAM,CAAC,CAAC,EAAE,CACtDO,IAAI;QAEPb,KAAIc,KAAK,CAAC,CAAC,uBAAuB,EAAEN,cAAc;QAClD,OAAOA;IACT;AACF;AAKO,SAASf,iBAAiBU,WAAmB;IAClD,uEAAuE;IACvE,iGAAiG;IAEjG,IAAI;QACF,2IAA2I;QAC3I,MAAMY,0BAA0BvB,4BAC9BW,aACA,2BACAQ,IAAI,CACJ,kFAAkF;QAClF,wGAAwG;QACxG,qCAAqC;QACrC,CAACD,GAAGE,IAAMF,EAAEJ,MAAM,GAAGM,EAAEN,MAAM;QAE/B,sBAAsB;QACtB,MAAMU,oCAAoCxB,4BACxCW,aACA;QAGF,MAAMc,aAAaC,eAAI,CAACC,IAAI,CAC1B,oEAAoE;QACpEJ,uBAAuB,CAAC,EAAE,EAC1B,qCAAqC;QACrCC,iCAAiC,CAACA,kCAAkCV,MAAM,GAAG,EAAE;QAGjF,4FAA4F;QAC5F,OAAOZ,eAAeuB;IACxB,EAAE,OAAOG,OAAO;QACd,IAAIA,iBAAiBb,oBAAY,IAAIa,MAAMC,IAAI,KAAK,eAAe;YACjE,MAAMC,eAAexB,yBAAyBK;YAC9C,IAAImB,cAAc;gBAChB,OAAOA;YACT;QACF;QACA,MAAMF;IACR;AACF;AAEO,SAAS1B,eAAe6B,QAAgB;IAC7C,IAAIC,aAAE,CAACC,UAAU,CAACF,WAAW;QAC3B,OAAOA;IACT;IACA,MAAMG,gBAAgBH,SAASI,KAAK,CAAC,OAAOR,IAAI,CAAC;IACjD,IAAIK,aAAE,CAACC,UAAU,CAACC,gBAAgB;QAChC,OAAOA;IACT;IACA,MAAM,IAAInB,oBAAY,CACpB,eACA,CAAC,mCAAmC,EAAEgB,SAAS,sFAAsF,CAAC;AAE1I;AAEO,SAAS/B,4BAA4BW,WAAmB,EAAEyB,YAAoB;IACnF,6EAA6E;IAC7E,MAAMC,MAAM,IAAIC,OAAO,CAAC,OAAO,EAAEF,aAAa,WAAW,CAAC,EAAE;IAC5D,MAAMG,UAAU;WAAI5B,YAAY6B,QAAQ,CAACH;KAAK;IAE9C,IAAI,CAACE,WAAW,CAACA,QAAQzB,MAAM,EAAE;QAC/B,MAAM,IAAIC,oBAAY,CACpB,eACA,CAAC,+BAA+B,EAAEqB,aAAa,wGAAwG,CAAC;IAE5J;IACA,OAAOG,QAAQE,GAAG,CAAC,CAACC,QAAUA,KAAK,CAAC,EAAE,EAAEzB,MAAM,CAAC0B;AACjD;AAEO,SAASxC,kBAAkB,EAChCyC,QAAQ,EACRC,yBAAyB,EACzBC,QAAQ,EACRC,IAAI,EACJC,kBAAkB,EAOnB;IACC,MAAMC,gBAAgBJ,4BAA4B,MAAMK;IACxD,IAAIN,UAAU;QACZ,OAAO;YACLO,KAAK;gBACH,GAAGC,QAAQD,GAAG;gBACdE,cAAcP;gBACdG;gBACAK,gBAAgBP,KAAKQ,QAAQ;gBAC7BC,6BAA6BR;YAC/B;QACF;IACF;IAEA,OAAO;QACLG,KAAK;YACH,GAAGC,QAAQD,GAAG;YACdE,cAAcP;YACdG;YACAO,6BAA6BR;YAC7B,0DAA0D;YAC1D,4EAA4E;YAC5E,2EAA2E;YAC3ES,wBAAwB;QAE1B;IACF;AACF;AAEO,eAAerD,uBACpBsD,KASC;IAED,MAAMC,OAAO;QACXD,MAAME,YAAY,CAACC,WAAW,GAAG,eAAe;QAChDH,MAAME,YAAY,CAACE,IAAI;QACvB;QACAJ,MAAMK,aAAa;QACnB;QACAL,MAAMM,MAAM;QACZ;QACA,CAAC,GAAG,EAAEN,MAAMO,MAAM,CAACC,IAAI,EAAE;KAC1B;IAED,IAAI,CAACR,MAAMS,WAAW,IAAIC,IAAAA,uDAAiC,EAACV,MAAMW,WAAW,GAAG;QAC9E,MAAMC,oBAAoB,MAAMC,IAAAA,gEAA0C,EAACb,MAAMW,WAAW;QAC5F,IAAIC,mBAAmB;YACrBX,KAAKa,IAAI,CACP,CAAC,iBAAiB,EAAEF,mBAAmB,EACvC,6BACA;QAEJ;IACF;IAEA,WAAW;IACX,IAAIZ,MAAMe,UAAU,KAAK,OAAO;QAC9Bd,KAAKa,IAAI,CACP,4CAA4C;QAC5C,SACA,kFAAkF;QAClF;IAEJ;IACA,OAAOb;AACT;AAEA,SAASe,gBACPf,IAAc,EACdgB,OAAiC,EACjC,EAAEC,MAAM,EAAsC;IAE9C,MAAMC,eAAeC,IAAAA,sBAAK,EAAC,cAAcnB,MAAMgB;IAE/C,IAAII,UAAU;IACd,IAAInD,QAAQ;IAEZiD,aAAaG,MAAM,CAACC,EAAE,CAAC,QAAQ,CAACC;QAC9B,MAAMC,aAAaD,KAAK3B,QAAQ;QAChCwB,WAAWI;QACXP,OAAOO;IACT;IAEAN,aAAaO,MAAM,CAACH,EAAE,CAAC,QAAQ,CAACC;QAC9B,MAAMC,aAAaD,gBAAgBG,SAASH,KAAK3B,QAAQ,KAAK2B;QAC9DtD,SAASuD;IACX;IAEA,OAAO,IAAIG,QAAQ,OAAOC,SAASC;QACjCX,aAAaI,EAAE,CAAC,SAAS,CAACpD;YACxB0D,QAAQ;gBAAE1D;gBAAMkD;gBAASnD;YAAM;QACjC;IACF;AACF;AAEA,eAAe6D,yBACb9B,IAAc,EACdgB,OAAiC,EACjC,EAAEe,OAAO,EAAuC;IAEhD,IAAIC,gBAAgB;IAEpB,uEAAuE;IACvE,6GAA6G;IAC7G,SAASC;QACP,IAAI,CAACD,eAAe;YAClB;QACF;QAEA,MAAMT,OAAOS;QACb,gBAAgB;QAChBA,gBAAgB;QAChB,gBAAgB;QAChBD,QAAQR;IACV;IAEA,MAAMA,OAAO,MAAMR,gBAAgBf,MAAMgB,SAAS;QAChDC,QAAOO,UAAU;YACfQ,iBAAiBR;YACjB,8CAA8C;YAC9C,IAAIQ,cAAcE,QAAQ,CAACC,aAAE,CAACC,GAAG,GAAG;gBAClCH;YACF;QACF;IACF;IAEA,8DAA8D;IAC9DA;IACA,OAAOV;AACT;AAEA,eAAec,0BACbrC,IAAc,EACdgB,OAAiC,EACjC,EAAEN,WAAW,EAAET,YAAY,EAAsD;IAEjFpD,KAAIc,KAAK,CAAC,CAAC,aAAa,EAAEqC,KAAKhC,IAAI,CAAC,MAAM;IAE1CtB,cAAcK,gBAAK,CAACuF,IAAI,CAAC,cAAc,CAAC;IAExC,MAAMC,YAAYC,4BAAgB,CAACC,MAAM,CAAC/B,aAAa;QACrDT;QACAyC,SAASlD,QAAG,CAACmD,UAAU;IACzB;IAEA,MAAMvB,UAAU,MAAMU,yBAAyB9B,MAAMgB,SAAS;QAC5De,SAAQR,IAAI;YACV,gBAAgB;YAChB,KAAK,MAAMqB,QAAQL,UAAUM,IAAI,CAACtB,MAAO;gBACvC,sBAAsB;gBACtB1E,KAAIC,GAAG,CAAC8F;YACV;QACF;IACF;IAEA/F,KAAIc,KAAK,CAAC,CAAC,kBAAkB,EAAEyD,QAAQlD,IAAI,EAAE;IAE7C,IACE,6BAA6B;IAC7BkD,QAAQlD,IAAI,KAAK,QACjB,oBAAoB;IACpBkD,QAAQlD,IAAI,KAAK,IACjB;QACA,MAAM,IAAI4E,yBAAiB;IAC7B;IAEAjG,KAAIC,GAAG,CAACyF,UAAUQ,eAAe;IAEjC,OAAO;QAAE,GAAG3B,OAAO;QAAEmB;IAAU;AACjC;AAEO,eAAenG,WAAW2D,KAAiB;IAChD,MAAMC,OAAO,MAAMvD,uBAAuBsD;IAE1C,MAAM,EAAEW,WAAW,EAAET,YAAY,EAAEf,yBAAyB,EAAEE,IAAI,EAAEC,kBAAkB,EAAE,GAAGU;IAE3F,MAAM,EAAE7B,IAAI,EAAEkD,OAAO,EAAEmB,SAAS,EAAEtE,KAAK,EAAE,GAAG,MAAMoE,0BAChDrC,MACAxD,kBAAkB;QAChByC,UAAU;QACVE,UAAU6D,IAAAA,yBAAe;QACzB9D;QACAE;QACAC;IACF,IACA;QACEqB;QACAT;IACF;IAGF,MAAMgD,cAAcC,eAAexC,aAAaU,SAASnD;IAEzD,IAAIC,SAAS,GAAG;QACd,4CAA4C;QAC5C,MAAMiF,oBAAoB,CAAC,CAACZ,UAAUa,MAAM,CAACjG,MAAM;QAEnD,IAAIgG,mBAAmB;YACrB,0HAA0H;YAC1H,8EAA8E;YAC9E,wEAAwE;YACxE,MAAM,IAAI/F,oBAAY,CACpB,CAAC,iEAAiE,EAAEc,KAAK,CAAC,CAAC;QAE/E;QAEA/B,yBAAyB+B,MAAMkD,SAASnD,OAAOgC,cAAcgD;IAC/D;IACA,OAAO7B;AACT;AAGO,SAASjF,yBACd+B,IAAmB,EACnBkD,OAAe,EACfnD,KAAa,EACbgC,YAA8B,EAC9BgD,WAAmB;QAYIhF;IAVvB,MAAMoF,aAAa,CAAC,iEAAiE,EAAEnF,KAAK,CAAC,CAAC;IAE9F,MAAMoF,mBAAmB,CAAC1G;QACxB,MAAM,IAAIQ,oBAAY,CACpB,GAAGiG,WAAW,gFAAgF,EAAEpD,aAAaE,IAAI,CAAC,KAAK,CAAC,GACtHvD,UACA,CAAC,sBAAsB,EAAEG,gBAAK,CAACwG,SAAS,CAACN,cAAc;IAE7D;IAEA,MAAMO,kBAAiBvF,eAAAA,MAAMf,KAAK,CAAC,mDAAZe,YAA4C,CAAC,EAAE;IAEtE,IAAIuF,gBAAgB;QAClBF,iBAAiBvG,gBAAK,CAACuF,IAAI,CAACkB,kBAAkB;IAChD;IACA,qFAAqF;IACrF,wEAAwE;IAExEF,iBAAiBlC,UAAU,SAASnD;AACtC;AAEA,SAASiF,eAAexC,WAAmB,EAAE1D,WAAmB,EAAEyG,WAAmB;IACnF,MAAM,CAACR,aAAaS,cAAc,GAAGC,oBAAoBjD;IAEzDrC,aAAE,CAACuF,aAAa,CAACX,aAAajG;IAC9BqB,aAAE,CAACuF,aAAa,CAACF,eAAeD;IAChC,OAAOR;AACT;AAEA,SAASU,oBAAoBjD,WAAmB;IAC9C,MAAMmD,SAAS9F,eAAI,CAACC,IAAI,CAAC0C,aAAa;IACtCoD,IAAAA,oBAAe,EAACD;IAChB,OAAO;QAAC9F,eAAI,CAACC,IAAI,CAAC6F,QAAQ;QAAmB9F,eAAI,CAACC,IAAI,CAAC6F,QAAQ;KAAwB;AACzF"}
1
+ {"version":3,"sources":["../../../../src/run/ios/XcodeBuild.ts"],"sourcesContent":["import { ExpoRunFormatter } from '@expo/xcpretty';\nimport chalk from 'chalk';\nimport { spawn, SpawnOptionsWithoutStdio } from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport { BuildProps, ProjectInfo } from './XcodeBuild.types';\nimport { ensureDeviceIsCodeSignedForDeploymentAsync } from './codeSigning/configureCodeSigning';\nimport { simulatorBuildRequiresCodeSigning } from './codeSigning/simulatorCodeSigning';\nimport * as Log from '../../log';\nimport { ensureDirectory } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { AbortCommandError, CommandError } from '../../utils/errors';\nimport { getUserTerminal } from '../../utils/terminal';\nexport function logPrettyItem(message: string) {\n Log.log(chalk`{whiteBright \\u203A} ${message}`);\n}\n\nexport function matchEstimatedBinaryPath(buildOutput: string): string | null {\n // Match the full path that contains `/(.*)/Developer/Xcode/DerivedData/(.*)/Build/Products/(.*)/(.*).app`\n const appBinaryPathMatch = buildOutput.match(\n /(\\/(?:\\\\\\s|[^ ])+\\/Developer\\/Xcode\\/DerivedData\\/(?:\\\\\\s|[^ ])+\\/Build\\/Products\\/(?:Debug|Release)-(?:[^\\s/]+)\\/(?:\\\\\\s|[^ ])+\\.app)/\n );\n if (!appBinaryPathMatch?.length) {\n throw new CommandError(\n 'XCODE_BUILD',\n `Malformed xcodebuild results: app binary path was not generated in build output. Report this issue and run your project with Xcode instead.`\n );\n } else {\n // Sort for the shortest\n const shortestPath = (appBinaryPathMatch.filter((a) => typeof a === 'string' && a) as string[])\n .sort((a: string, b: string) => a.length - b.length)[0]\n .trim();\n\n Log.debug(`Found app binary path: ${shortestPath}`);\n return shortestPath;\n }\n}\n/**\n *\n * @returns '/Users/evanbacon/Library/Developer/Xcode/DerivedData/myapp-gpgjqjodrxtervaufttwnsgimhrx/Build/Products/Debug-iphonesimulator/myapp.app'\n */\nexport function getAppBinaryPath(buildOutput: string) {\n // Matches what's used in \"Bundle React Native code and images\" script.\n // Requires that `-hideShellScriptEnvironment` is not included in the build command (extra logs).\n\n try {\n // Like `\\=/Users/evanbacon/Library/Developer/Xcode/DerivedData/Exponent-anpuosnglkxokahjhfszejloqfvo/Build/Products/Debug-iphonesimulator`\n const CONFIGURATION_BUILD_DIR = extractEnvVariableFromBuild(\n buildOutput,\n 'CONFIGURATION_BUILD_DIR'\n ).sort(\n // Longer name means more suffixes, we want the shortest possible one to be first.\n // Massive projects (like Expo Go) can sometimes print multiple different sets of environment variables.\n // This can become an issue with some\n (a, b) => a.length - b.length\n );\n // Like `Exponent.app`\n const UNLOCALIZED_RESOURCES_FOLDER_PATH = extractEnvVariableFromBuild(\n buildOutput,\n 'UNLOCALIZED_RESOURCES_FOLDER_PATH'\n );\n\n const binaryPath = path.join(\n // Use the shortest defined env variable (usually there's just one).\n CONFIGURATION_BUILD_DIR[0],\n // Use the last defined env variable.\n UNLOCALIZED_RESOURCES_FOLDER_PATH[UNLOCALIZED_RESOURCES_FOLDER_PATH.length - 1]\n );\n\n // If the app has a space in the name it'll fail because it isn't escaped properly by Xcode.\n return getEscapedPath(binaryPath);\n } catch (error) {\n if (error instanceof CommandError && error.code === 'XCODE_BUILD') {\n const possiblePath = matchEstimatedBinaryPath(buildOutput);\n if (possiblePath) {\n return possiblePath;\n }\n }\n throw error;\n }\n}\n\nexport function getEscapedPath(filePath: string): string {\n if (fs.existsSync(filePath)) {\n return filePath;\n }\n const unescapedPath = filePath.split(/\\\\ /).join(' ');\n if (fs.existsSync(unescapedPath)) {\n return unescapedPath;\n }\n throw new CommandError(\n 'XCODE_BUILD',\n `Unexpected: Generated app at path \"${filePath}\" cannot be read, the app cannot be installed. Report this and build onto a simulator.`\n );\n}\n\nexport function extractEnvVariableFromBuild(buildOutput: string, variableName: string) {\n // Xcode can sometimes escape `=` with a backslash or put the value in quotes\n const reg = new RegExp(`export ${variableName}\\\\\\\\?=(.*)$`, 'mg');\n const matched = [...buildOutput.matchAll(reg)];\n\n if (!matched || !matched.length) {\n throw new CommandError(\n 'XCODE_BUILD',\n `Malformed xcodebuild results: \"${variableName}\" variable was not generated in build output. Report this issue and run your project with Xcode instead.`\n );\n }\n return matched.map((value) => value[1]).filter(Boolean) as string[];\n}\n\nexport function getProcessOptions({\n packager,\n shouldSkipInitialBundling,\n terminal,\n port,\n eagerBundleOptions,\n}: {\n packager: boolean;\n shouldSkipInitialBundling?: boolean;\n terminal: string | undefined;\n port: number;\n eagerBundleOptions?: string;\n}): SpawnOptionsWithoutStdio {\n const SKIP_BUNDLING = shouldSkipInitialBundling ? '1' : undefined;\n if (packager) {\n return {\n env: {\n ...process.env,\n RCT_TERMINAL: terminal,\n SKIP_BUNDLING,\n RCT_METRO_PORT: port.toString(),\n __EXPO_EAGER_BUNDLE_OPTIONS: eagerBundleOptions,\n },\n };\n }\n\n return {\n env: {\n ...process.env,\n RCT_TERMINAL: terminal,\n SKIP_BUNDLING,\n __EXPO_EAGER_BUNDLE_OPTIONS: eagerBundleOptions,\n // Always skip launching the packager from a build script.\n // The script is used for people building their project directly from Xcode.\n // This essentially means \"› Running script 'Start Packager'\" does nothing.\n RCT_NO_LAUNCH_PACKAGER: 'true',\n // FORCE_BUNDLING: '0'\n },\n };\n}\n\nexport async function getXcodeBuildArgsAsync(\n props: Pick<\n BuildProps,\n | 'buildCache'\n | 'projectRoot'\n | 'xcodeProject'\n | 'configuration'\n | 'scheme'\n | 'device'\n | 'isSimulator'\n >\n): Promise<string[]> {\n const args = [\n props.xcodeProject.isWorkspace ? '-workspace' : '-project',\n props.xcodeProject.name,\n '-configuration',\n props.configuration,\n '-scheme',\n props.scheme,\n '-destination',\n `id=${props.device.udid}`,\n ];\n\n if (!props.isSimulator || simulatorBuildRequiresCodeSigning(props.projectRoot)) {\n const developmentTeamId = await ensureDeviceIsCodeSignedForDeploymentAsync(props.projectRoot);\n if (developmentTeamId) {\n args.push(\n `DEVELOPMENT_TEAM=${developmentTeamId}`,\n '-allowProvisioningUpdates',\n '-allowProvisioningDeviceRegistration'\n );\n }\n }\n\n // Add last\n if (props.buildCache === false) {\n args.push(\n // Will first clean the derived data folder.\n 'clean',\n // Then build step must be added otherwise the process will simply clean and exit.\n 'build'\n );\n }\n return args;\n}\n\nfunction spawnXcodeBuild(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { onData }: { onData: (data: string) => void }\n): Promise<{ code: number | null; results: string; error: string }> {\n const buildProcess = spawn('xcodebuild', args, options);\n\n let results = '';\n let error = '';\n\n buildProcess.stdout.on('data', (data: Buffer) => {\n const stringData = data.toString();\n results += stringData;\n onData(stringData);\n });\n\n buildProcess.stderr.on('data', (data: Buffer) => {\n const stringData = data instanceof Buffer ? data.toString() : data;\n error += stringData;\n });\n\n return new Promise(async (resolve, reject) => {\n buildProcess.on('close', (code: number) => {\n resolve({ code, results, error });\n });\n });\n}\n\nasync function spawnXcodeBuildWithFlush(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { onFlush }: { onFlush: (data: string) => void }\n): Promise<{ code: number | null; results: string; error: string }> {\n let currentBuffer = '';\n\n // Data can be sent in chunks that would have no relevance to our regex\n // this can cause massive slowdowns, so we need to ensure the data is complete before attempting to parse it.\n function flushBuffer() {\n if (!currentBuffer) {\n return;\n }\n\n const data = currentBuffer;\n // Reset buffer.\n currentBuffer = '';\n // Process data.\n onFlush(data);\n }\n\n const data = await spawnXcodeBuild(args, options, {\n onData(stringData) {\n currentBuffer += stringData;\n // Only flush the data if we have a full line.\n if (currentBuffer.endsWith(os.EOL)) {\n flushBuffer();\n }\n },\n });\n\n // Flush log data at the end just in case we missed something.\n flushBuffer();\n return data;\n}\n\nasync function spawnXcodeBuildWithFormat(\n args: string[],\n options: SpawnOptionsWithoutStdio,\n { projectRoot, xcodeProject }: { projectRoot: string; xcodeProject: ProjectInfo }\n): Promise<{ code: number | null; results: string; error: string; formatter: ExpoRunFormatter }> {\n Log.debug(` xcodebuild ${args.join(' ')}`);\n\n logPrettyItem(chalk.bold`Planning build`);\n\n const formatter = ExpoRunFormatter.create(projectRoot, {\n xcodeProject,\n isDebug: env.EXPO_DEBUG,\n });\n\n const results = await spawnXcodeBuildWithFlush(args, options, {\n onFlush(data) {\n // Process data.\n for (const line of formatter.pipe(data)) {\n // Log parsed results.\n Log.log(line);\n }\n },\n });\n\n Log.debug(`Exited with code: ${results.code}`);\n\n if (\n // User cancelled with ctrl-c\n results.code === null ||\n // Build interrupted\n results.code === 75\n ) {\n throw new AbortCommandError();\n }\n\n Log.log(formatter.getBuildSummary());\n\n return { ...results, formatter };\n}\n\nexport async function buildAsync(props: BuildProps): Promise<string> {\n const args = await getXcodeBuildArgsAsync(props);\n\n const { projectRoot, xcodeProject, shouldSkipInitialBundling, port, eagerBundleOptions } = props;\n\n const { code, results, formatter, error } = await spawnXcodeBuildWithFormat(\n args,\n getProcessOptions({\n packager: false,\n terminal: getUserTerminal(),\n shouldSkipInitialBundling,\n port,\n eagerBundleOptions,\n }),\n {\n projectRoot,\n xcodeProject,\n }\n );\n\n const logFilePath = writeBuildLogs(projectRoot, results, error);\n\n if (code !== 0) {\n // Determine if the logger found any errors;\n const wasErrorPresented = !!formatter.errors.length;\n\n if (wasErrorPresented) {\n // This has a flaw, if the user is missing a file, and there is a script error, only the missing file error will be shown.\n // They will only see the script error if they fix the missing file and rerun.\n // The flaw can be fixed by catching script errors in the custom logger.\n throw new CommandError(\n `Failed to build iOS project. \"xcodebuild\" exited with error code ${code}.`\n );\n }\n\n _assertXcodeBuildResults(code, results, error, xcodeProject, logFilePath);\n }\n return results;\n}\n\n// Exposed for testing.\nexport function _assertXcodeBuildResults(\n code: number | null,\n results: string,\n error: string,\n xcodeProject: { name: string },\n logFilePath: string\n): void {\n const errorTitle = `Failed to build iOS project. \"xcodebuild\" exited with error code ${code}.`;\n\n const throwWithMessage = (message: string): never => {\n throw new CommandError(\n `${errorTitle}\\nTo view more error logs, try building the app with Xcode directly, by opening ${xcodeProject.name}.\\n\\n` +\n message +\n `Build logs written to ${chalk.underline(logFilePath)}`\n );\n };\n\n const localizedError = error.match(/NSLocalizedFailure = \"(.*)\"/)?.[1];\n\n if (localizedError) {\n throwWithMessage(chalk.bold(localizedError) + '\\n\\n');\n }\n\n // `@expo/xcpretty` can leave a real failure uncounted (its compile-error\n // matching is stateful and anchored, and stderr never passes through it), so\n // the build summary reads \"0 error(s)\" and in CI the full log below is\n // truncated before the real error line.\n const errorLines = _extractXcodeBuildErrorLines(results + '\\n' + error);\n if (errorLines.length) {\n throwWithMessage(chalk.red(errorLines.join('\\n')) + '\\n\\n' + results + '\\n\\n' + error);\n }\n\n // Show all the log info because often times the error is coming from a shell script,\n // that invoked a node script, that started metro, which threw an error.\n\n throwWithMessage(results + '\\n\\n' + error);\n}\n\n// Exposed for testing.\nexport function _extractXcodeBuildErrorLines(output: string): string[] {\n const seen = new Set<string>();\n const errors: string[] = [];\n for (const raw of output.split(/\\r?\\n/)) {\n const line = raw.trim();\n if (/(?:^|\\s)error:\\s/.test(line) && !seen.has(line)) {\n seen.add(line);\n errors.push(line);\n }\n }\n return errors;\n}\n\nfunction writeBuildLogs(projectRoot: string, buildOutput: string, errorOutput: string) {\n const [logFilePath, errorFilePath] = getErrorLogFilePath(projectRoot);\n\n fs.writeFileSync(logFilePath, buildOutput);\n fs.writeFileSync(errorFilePath, errorOutput);\n return logFilePath;\n}\n\nfunction getErrorLogFilePath(projectRoot: string): [string, string] {\n const folder = path.join(projectRoot, '.expo');\n ensureDirectory(folder);\n return [path.join(folder, 'xcodebuild.log'), path.join(folder, 'xcodebuild-error.log')];\n}\n"],"names":["_assertXcodeBuildResults","_extractXcodeBuildErrorLines","buildAsync","extractEnvVariableFromBuild","getAppBinaryPath","getEscapedPath","getProcessOptions","getXcodeBuildArgsAsync","logPrettyItem","matchEstimatedBinaryPath","message","Log","log","chalk","buildOutput","appBinaryPathMatch","match","length","CommandError","shortestPath","filter","a","sort","b","trim","debug","CONFIGURATION_BUILD_DIR","UNLOCALIZED_RESOURCES_FOLDER_PATH","binaryPath","path","join","error","code","possiblePath","filePath","fs","existsSync","unescapedPath","split","variableName","reg","RegExp","matched","matchAll","map","value","Boolean","packager","shouldSkipInitialBundling","terminal","port","eagerBundleOptions","SKIP_BUNDLING","undefined","env","process","RCT_TERMINAL","RCT_METRO_PORT","toString","__EXPO_EAGER_BUNDLE_OPTIONS","RCT_NO_LAUNCH_PACKAGER","props","args","xcodeProject","isWorkspace","name","configuration","scheme","device","udid","isSimulator","simulatorBuildRequiresCodeSigning","projectRoot","developmentTeamId","ensureDeviceIsCodeSignedForDeploymentAsync","push","buildCache","spawnXcodeBuild","options","onData","buildProcess","spawn","results","stdout","on","data","stringData","stderr","Buffer","Promise","resolve","reject","spawnXcodeBuildWithFlush","onFlush","currentBuffer","flushBuffer","endsWith","os","EOL","spawnXcodeBuildWithFormat","bold","formatter","ExpoRunFormatter","create","isDebug","EXPO_DEBUG","line","pipe","AbortCommandError","getBuildSummary","getUserTerminal","logFilePath","writeBuildLogs","wasErrorPresented","errors","errorTitle","throwWithMessage","underline","localizedError","errorLines","red","output","seen","Set","raw","test","has","add","errorOutput","errorFilePath","getErrorLogFilePath","writeFileSync","folder","ensureDirectory"],"mappings":"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"}
@@ -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,