@expo/cli 55.0.32 → 55.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bin/cli +1 -1
- package/build/src/events/index.js +1 -1
- package/build/src/export/createMetadataJson.js.map +1 -1
- package/build/src/export/embed/exportEmbedAsync.js +6 -3
- package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
- package/build/src/export/embed/resolveOptions.js +2 -1
- package/build/src/export/embed/resolveOptions.js.map +1 -1
- package/build/src/export/exportApp.js +1 -1
- package/build/src/export/exportApp.js.map +1 -1
- package/build/src/export/exportHermes.js +10 -1
- package/build/src/export/exportHermes.js.map +1 -1
- package/build/src/export/resolveOptions.js +9 -10
- package/build/src/export/resolveOptions.js.map +1 -1
- package/build/src/export/saveAssets.js.map +1 -1
- package/build/src/export/static.js +6 -0
- package/build/src/export/static.js.map +1 -0
- package/build/src/run/android/resolveInstallApkName.js +48 -1
- package/build/src/run/android/resolveInstallApkName.js.map +1 -1
- package/build/src/run/ios/XcodeBuild.js +23 -0
- package/build/src/run/ios/XcodeBuild.js.map +1 -1
- package/build/src/run/ios/appleDevice/client/LockdowndClient.js +1 -1
- package/build/src/run/ios/appleDevice/client/LockdowndClient.js.map +1 -1
- package/build/src/serve/serveAsync.js +23 -11
- package/build/src/serve/serveAsync.js.map +1 -1
- package/build/src/serve/static.js +69 -0
- package/build/src/serve/static.js.map +1 -0
- package/build/src/start/server/metro/createExpoAutolinkingResolver.js +21 -8
- package/build/src/start/server/metro/createExpoAutolinkingResolver.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +5 -2
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js +89 -28
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js +3 -1
- package/build/src/start/server/middleware/ExpoGoManifestHandlerMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/InterstitialPageMiddleware.js +3 -1
- package/build/src/start/server/middleware/InterstitialPageMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/resolvePlatform.js +4 -2
- package/build/src/start/server/middleware/resolvePlatform.js.map +1 -1
- package/build/src/start/server/platformBundlers.js +3 -1
- package/build/src/start/server/platformBundlers.js.map +1 -1
- package/build/src/utils/findUp.js +17 -19
- package/build/src/utils/findUp.js.map +1 -1
- package/build/src/utils/qr.js +5 -4
- package/build/src/utils/qr.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +14 -14
|
@@ -25,31 +25,29 @@ function _config() {
|
|
|
25
25
|
}
|
|
26
26
|
const _platformBundlers = require("../start/server/platformBundlers");
|
|
27
27
|
const _errors = require("../utils/errors");
|
|
28
|
-
function resolvePlatformOption(
|
|
28
|
+
function resolvePlatformOption(configPlatforms, platformBundlers, platform = [
|
|
29
29
|
'all'
|
|
30
30
|
]) {
|
|
31
|
-
const platformsAvailable = Object.fromEntries(Object.entries(platformBundlers).filter(([platform, bundler])=>
|
|
32
|
-
var _exp_platforms;
|
|
33
|
-
return bundler === 'metro' && ((_exp_platforms = exp.platforms) == null ? void 0 : _exp_platforms.includes(platform));
|
|
34
|
-
}));
|
|
31
|
+
const platformsAvailable = Object.fromEntries(Object.entries(platformBundlers).filter(([platform, bundler])=>bundler === 'metro' && configPlatforms.includes(platform)));
|
|
35
32
|
if (!Object.keys(platformsAvailable).length) {
|
|
36
33
|
throw new _errors.CommandError(`No platforms are configured to use the Metro bundler in the project Expo config.`);
|
|
37
34
|
}
|
|
38
35
|
const assertPlatformBundler = (platform)=>{
|
|
39
36
|
if (!platformsAvailable[platform]) {
|
|
40
|
-
|
|
41
|
-
if (!((_exp_platforms = exp.platforms) == null ? void 0 : _exp_platforms.includes(platform)) && platform === 'web') {
|
|
37
|
+
if (!configPlatforms.includes(platform) && platform === 'web') {
|
|
42
38
|
// Pass through so the more robust error message is shown.
|
|
43
39
|
return platform;
|
|
44
40
|
}
|
|
45
|
-
throw new _errors.CommandError('BAD_ARGS', `Platform "${platform}" is not configured to use the Metro bundler in the project Expo config, or is missing from the supported platforms in the platforms array: [${
|
|
41
|
+
throw new _errors.CommandError('BAD_ARGS', `Platform "${platform}" is not configured to use the Metro bundler in the project Expo config, or is missing from the supported platforms in the platforms array: [${configPlatforms.join(', ')}].`);
|
|
46
42
|
}
|
|
47
43
|
return platform;
|
|
48
44
|
};
|
|
49
45
|
const knownPlatforms = [
|
|
50
46
|
'android',
|
|
51
47
|
'ios',
|
|
52
|
-
'web'
|
|
48
|
+
'web',
|
|
49
|
+
'tvos',
|
|
50
|
+
'macos'
|
|
53
51
|
];
|
|
54
52
|
const assertPlatformIsKnown = (platform)=>{
|
|
55
53
|
if (!knownPlatforms.includes(platform)) {
|
|
@@ -68,7 +66,8 @@ async function resolveOptionsAsync(projectRoot, args) {
|
|
|
68
66
|
skipSDKVersionRequirement: true
|
|
69
67
|
});
|
|
70
68
|
const platformBundlers = (0, _platformBundlers.getPlatformBundlers)(projectRoot, exp);
|
|
71
|
-
const
|
|
69
|
+
const platformsFromConfig = (0, _config().getPlatformsFromConfig)(projectRoot, exp);
|
|
70
|
+
const platforms = resolvePlatformOption(platformsFromConfig, platformBundlers, args['--platform']);
|
|
72
71
|
// --source-maps can be true, "external", or "inline"
|
|
73
72
|
const sourceMapsArg = args['--source-maps'];
|
|
74
73
|
const sourceMaps = !!sourceMapsArg;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/export/resolveOptions.ts"],"sourcesContent":["import { ExpoConfig, getConfig,
|
|
1
|
+
{"version":3,"sources":["../../../src/export/resolveOptions.ts"],"sourcesContent":["import type { ExpoConfig, Platform } from '@expo/config';\nimport { getConfig, getPlatformsFromConfig } from '@expo/config';\n\nimport { getPlatformBundlers, PlatformBundlers } from '../start/server/platformBundlers';\nimport { CommandError } from '../utils/errors';\n\nexport type Options = {\n outputDir: string;\n platforms: Platform[];\n maxWorkers?: number;\n dev: boolean;\n clear: boolean;\n minify: boolean;\n bytecode: boolean;\n dumpAssetmap: boolean;\n sourceMaps: boolean;\n inlineSourceMaps: boolean;\n skipSSG: boolean;\n hostedNative: boolean;\n};\n\n/** Returns an array of platforms based on the input platform identifier and runtime constraints. */\nexport function resolvePlatformOption(\n configPlatforms: Platform[],\n platformBundlers: PlatformBundlers,\n platform: string[] = ['all']\n): Platform[] {\n const platformsAvailable: Partial<PlatformBundlers> = Object.fromEntries(\n Object.entries(platformBundlers).filter(\n ([platform, bundler]) => bundler === 'metro' && configPlatforms.includes(platform as Platform)\n )\n );\n\n if (!Object.keys(platformsAvailable).length) {\n throw new CommandError(\n `No platforms are configured to use the Metro bundler in the project Expo config.`\n );\n }\n\n const assertPlatformBundler = (platform: Platform): Platform => {\n if (!platformsAvailable[platform]) {\n if (!configPlatforms.includes(platform) && platform === 'web') {\n // Pass through so the more robust error message is shown.\n return platform;\n }\n throw new CommandError(\n 'BAD_ARGS',\n `Platform \"${platform}\" is not configured to use the Metro bundler in the project Expo config, or is missing from the supported platforms in the platforms array: [${configPlatforms.join(\n ', '\n )}].`\n );\n }\n\n return platform;\n };\n\n const knownPlatforms = ['android', 'ios', 'web', 'tvos', 'macos'] as Platform[];\n const assertPlatformIsKnown = (platform: string): Platform => {\n if (!knownPlatforms.includes(platform as Platform)) {\n throw new CommandError(\n `Unsupported platform \"${platform}\". Options are: ${knownPlatforms.join(',')},all`\n );\n }\n\n return platform as Platform;\n };\n\n return (\n platform\n // Expand `all` to all available platforms.\n .map((platform) => (platform === 'all' ? Object.keys(platformsAvailable) : platform))\n .flat()\n // Remove duplicated platforms\n .filter((platform, index, list) => list.indexOf(platform) === index)\n // Assert platforms are valid\n .map((platform) => assertPlatformIsKnown(platform))\n .map((platform) => assertPlatformBundler(platform))\n );\n}\n\nexport async function resolveOptionsAsync(projectRoot: string, args: any): Promise<Options> {\n const { exp } = getConfig(projectRoot, { skipPlugins: true, skipSDKVersionRequirement: true });\n const platformBundlers = getPlatformBundlers(projectRoot, exp);\n\n const platformsFromConfig = getPlatformsFromConfig(projectRoot, exp);\n const platforms = resolvePlatformOption(\n platformsFromConfig,\n platformBundlers,\n args['--platform']\n );\n\n // --source-maps can be true, \"external\", or \"inline\"\n const sourceMapsArg = args['--source-maps'];\n const sourceMaps = !!sourceMapsArg;\n const inlineSourceMaps = sourceMapsArg === 'inline';\n\n return {\n platforms,\n hostedNative: !!args['--unstable-hosted-native'],\n outputDir: args['--output-dir'] ?? 'dist',\n minify: !args['--no-minify'],\n bytecode: !args['--no-bytecode'],\n clear: !!args['--clear'],\n dev: !!args['--dev'],\n maxWorkers: args['--max-workers'],\n dumpAssetmap: !!args['--dump-assetmap'],\n sourceMaps,\n inlineSourceMaps,\n skipSSG: !!args['--no-ssg'] || !!args['--api-only'],\n };\n}\n"],"names":["resolveOptionsAsync","resolvePlatformOption","configPlatforms","platformBundlers","platform","platformsAvailable","Object","fromEntries","entries","filter","bundler","includes","keys","length","CommandError","assertPlatformBundler","join","knownPlatforms","assertPlatformIsKnown","map","flat","index","list","indexOf","projectRoot","args","exp","getConfig","skipPlugins","skipSDKVersionRequirement","getPlatformBundlers","platformsFromConfig","getPlatformsFromConfig","platforms","sourceMapsArg","sourceMaps","inlineSourceMaps","hostedNative","outputDir","minify","bytecode","clear","dev","maxWorkers","dumpAssetmap","skipSSG"],"mappings":";;;;;;;;;;;IAgFsBA,mBAAmB;eAAnBA;;IA1DNC,qBAAqB;eAArBA;;;;yBArBkC;;;;;;kCAEI;wBACzB;AAkBtB,SAASA,sBACdC,eAA2B,EAC3BC,gBAAkC,EAClCC,WAAqB;IAAC;CAAM;IAE5B,MAAMC,qBAAgDC,OAAOC,WAAW,CACtED,OAAOE,OAAO,CAACL,kBAAkBM,MAAM,CACrC,CAAC,CAACL,UAAUM,QAAQ,GAAKA,YAAY,WAAWR,gBAAgBS,QAAQ,CAACP;IAI7E,IAAI,CAACE,OAAOM,IAAI,CAACP,oBAAoBQ,MAAM,EAAE;QAC3C,MAAM,IAAIC,oBAAY,CACpB,CAAC,gFAAgF,CAAC;IAEtF;IAEA,MAAMC,wBAAwB,CAACX;QAC7B,IAAI,CAACC,kBAAkB,CAACD,SAAS,EAAE;YACjC,IAAI,CAACF,gBAAgBS,QAAQ,CAACP,aAAaA,aAAa,OAAO;gBAC7D,0DAA0D;gBAC1D,OAAOA;YACT;YACA,MAAM,IAAIU,oBAAY,CACpB,YACA,CAAC,UAAU,EAAEV,SAAS,6IAA6I,EAAEF,gBAAgBc,IAAI,CACvL,MACA,EAAE,CAAC;QAET;QAEA,OAAOZ;IACT;IAEA,MAAMa,iBAAiB;QAAC;QAAW;QAAO;QAAO;QAAQ;KAAQ;IACjE,MAAMC,wBAAwB,CAACd;QAC7B,IAAI,CAACa,eAAeN,QAAQ,CAACP,WAAuB;YAClD,MAAM,IAAIU,oBAAY,CACpB,CAAC,sBAAsB,EAAEV,SAAS,gBAAgB,EAAEa,eAAeD,IAAI,CAAC,KAAK,IAAI,CAAC;QAEtF;QAEA,OAAOZ;IACT;IAEA,OACEA,QACE,2CAA2C;KAC1Ce,GAAG,CAAC,CAACf,WAAcA,aAAa,QAAQE,OAAOM,IAAI,CAACP,sBAAsBD,UAC1EgB,IAAI,EACL,8BAA8B;KAC7BX,MAAM,CAAC,CAACL,UAAUiB,OAAOC,OAASA,KAAKC,OAAO,CAACnB,cAAciB,MAC9D,6BAA6B;KAC5BF,GAAG,CAAC,CAACf,WAAac,sBAAsBd,WACxCe,GAAG,CAAC,CAACf,WAAaW,sBAAsBX;AAE/C;AAEO,eAAeJ,oBAAoBwB,WAAmB,EAAEC,IAAS;IACtE,MAAM,EAAEC,GAAG,EAAE,GAAGC,IAAAA,mBAAS,EAACH,aAAa;QAAEI,aAAa;QAAMC,2BAA2B;IAAK;IAC5F,MAAM1B,mBAAmB2B,IAAAA,qCAAmB,EAACN,aAAaE;IAE1D,MAAMK,sBAAsBC,IAAAA,gCAAsB,EAACR,aAAaE;IAChE,MAAMO,YAAYhC,sBAChB8B,qBACA5B,kBACAsB,IAAI,CAAC,aAAa;IAGpB,qDAAqD;IACrD,MAAMS,gBAAgBT,IAAI,CAAC,gBAAgB;IAC3C,MAAMU,aAAa,CAAC,CAACD;IACrB,MAAME,mBAAmBF,kBAAkB;IAE3C,OAAO;QACLD;QACAI,cAAc,CAAC,CAACZ,IAAI,CAAC,2BAA2B;QAChDa,WAAWb,IAAI,CAAC,eAAe,IAAI;QACnCc,QAAQ,CAACd,IAAI,CAAC,cAAc;QAC5Be,UAAU,CAACf,IAAI,CAAC,gBAAgB;QAChCgB,OAAO,CAAC,CAAChB,IAAI,CAAC,UAAU;QACxBiB,KAAK,CAAC,CAACjB,IAAI,CAAC,QAAQ;QACpBkB,YAAYlB,IAAI,CAAC,gBAAgB;QACjCmB,cAAc,CAAC,CAACnB,IAAI,CAAC,kBAAkB;QACvCU;QACAC;QACAS,SAAS,CAAC,CAACpB,IAAI,CAAC,WAAW,IAAI,CAAC,CAACA,IAAI,CAAC,aAAa;IACrD;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/export/saveAssets.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport type { AssetData } from '@expo/metro/metro';\nimport type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { Log } from '../log';\nimport { env } from '../utils/env';\n\nlet bytesFormatter: Intl.NumberFormat | undefined | null;\n\nconst prettyBytes = (bytes: number): string => {\n try {\n if (bytesFormatter === undefined && typeof Intl === 'object') {\n bytesFormatter = new Intl.NumberFormat('en', {\n notation: 'compact',\n style: 'unit',\n unit: 'byte',\n unitDisplay: 'narrow',\n });\n }\n if (bytesFormatter != null) {\n return bytesFormatter.format(bytes);\n }\n } catch {\n bytesFormatter = null;\n }\n // Fall back if ICU is unavailable, which is rare but possible with custom Node.js builds\n if (bytes >= 900_000) {\n return `${(bytes / 1_000_000).toFixed(1)}MB`;\n } else if (bytes >= 900) {\n return `${(bytes / 1_000).toFixed(1)}KB`;\n } else {\n return `${bytes}B`;\n }\n};\n\nconst BLT = '\\u203A';\n\nexport type BundleOptions = {\n entryPoint: string;\n platform: 'android' | 'ios' | 'web';\n dev?: boolean;\n minify?: boolean;\n bytecode: boolean;\n sourceMapUrl?: string;\n sourcemaps?: boolean;\n};\n\nexport type BundleAssetWithFileHashes = AssetData & {\n fileHashes: string[]; // added by the hashAssets asset plugin\n};\n\nexport type BundleOutput = {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n};\n\nexport type ManifestAsset = { fileHashes: string[]; files: string[]; hash: string };\n\nexport type Asset = ManifestAsset | BundleAssetWithFileHashes;\n\nexport type ExportAssetDescriptor = {\n contents: string | Buffer;\n originFilename?: string;\n /** An identifier for grouping together variations of the same asset. */\n assetId?: string;\n /** Expo Router route path for formatting the HTML output. */\n routeId?: string;\n /** Expo Router route path for formatting the middleware function output. */\n middlewareId?: string;\n /** Expo Router API route path for formatting the server function output. */\n apiRouteId?: string;\n /** Expo Router route path for formatting the RSC output. */\n rscId?: string;\n /** Expo Router route path for formatting the loader module output. */\n loaderId?: string;\n /** A key for grouping together output files by server- or client-side. */\n targetDomain?: 'server' | 'client';\n};\n\nexport type ExportAssetMap = Map<string, ExportAssetDescriptor>;\n\nexport async function persistMetroFilesAsync(files: ExportAssetMap, outputDir: string) {\n if (!files.size) {\n return;\n }\n await fs.promises.mkdir(path.join(outputDir), { recursive: true });\n\n // Test fixtures:\n // Log.log(\n // JSON.stringify(\n // Object.fromEntries([...files.entries()].map(([k, v]) => [k, { ...v, contents: '' }]))\n // )\n // );\n\n const assetEntries: [string, ExportAssetDescriptor][] = [];\n const apiRouteEntries: [string, ExportAssetDescriptor][] = [];\n const middlewareEntries: [string, ExportAssetDescriptor][] = [];\n const routeEntries: [string, ExportAssetDescriptor][] = [];\n const rscEntries: [string, ExportAssetDescriptor][] = [];\n const loaderEntries: [string, ExportAssetDescriptor][] = [];\n const remainingEntries: [string, ExportAssetDescriptor][] = [];\n\n let hasServerOutput = false;\n for (const asset of files.entries()) {\n hasServerOutput = hasServerOutput || asset[1].targetDomain === 'server';\n if (asset[1].assetId) assetEntries.push(asset);\n else if (asset[1].routeId != null) routeEntries.push(asset);\n else if (asset[1].middlewareId != null) middlewareEntries.push(asset);\n else if (asset[1].apiRouteId != null) apiRouteEntries.push(asset);\n else if (asset[1].rscId != null) rscEntries.push(asset);\n else if (asset[1].loaderId != null) loaderEntries.push(asset);\n else remainingEntries.push(asset);\n }\n\n const groups = groupBy(assetEntries, ([, { assetId }]) => assetId!);\n\n const contentSize = (contents: string | Buffer) => {\n const length =\n typeof contents === 'string' ? Buffer.byteLength(contents, 'utf8') : contents.length;\n return length;\n };\n\n const sizeStr = (contents: string | Buffer) => {\n const length = contentSize(contents);\n const size = chalk.gray`(${prettyBytes(length)})`;\n return size;\n };\n\n // TODO: If any Expo Router is used, then use a new style which is more simple:\n // `chalk.gray(/path/to/) + chalk.cyan('route')`\n // | index.html (1.2kb)\n // | /path\n // | other.html (1.2kb)\n\n const isExpoRouter = routeEntries.length;\n\n // Phase out printing all the assets as users can simply check the file system for more info.\n const showAdditionalInfo = !isExpoRouter || env.EXPO_DEBUG;\n\n const assetGroups = [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0])) as [\n string,\n [string, ExportAssetDescriptor][],\n ][];\n\n if (showAdditionalInfo) {\n if (assetGroups.length) {\n const totalAssets = assetGroups.reduce((sum, [, assets]) => sum + assets.length, 0);\n\n Log.log('');\n Log.log(chalk.bold`${BLT} Assets (${totalAssets}):`);\n\n for (const [assetId, assets] of assetGroups) {\n const averageContentSize =\n assets.reduce((sum, [, { contents }]) => sum + contentSize(contents), 0) / assets.length;\n Log.log(\n assetId,\n chalk.gray(\n `(${[\n assets.length > 1 ? `${assets.length} variations` : '',\n `${prettyBytes(averageContentSize)}`,\n ]\n .filter(Boolean)\n .join(' | ')})`\n )\n );\n }\n }\n }\n\n const bundles: Map<string, [string, ExportAssetDescriptor][]> = new Map();\n const other: [string, ExportAssetDescriptor][] = [];\n\n remainingEntries.forEach(([filepath, asset]) => {\n if (!filepath.match(/_expo\\/(server|static)\\//)) {\n other.push([filepath, asset]);\n } else {\n const platform = filepath.match(/_expo\\/static\\/js\\/([^/]+)\\//)?.[1] ?? 'web';\n if (!bundles.has(platform)) bundles.set(platform, []);\n\n bundles.get(platform)!.push([filepath, asset]);\n }\n });\n\n [...bundles.entries()].forEach(([platform, assets]) => {\n Log.log('');\n Log.log(chalk.bold`${BLT} ${platform} bundles (${assets.length}):`);\n\n const allAssets = assets.sort((a, b) => a[0].localeCompare(b[0]));\n while (allAssets.length) {\n const [filePath, asset] = allAssets.shift()!;\n Log.log(filePath, sizeStr(asset.contents));\n if (filePath.match(/\\.(js|hbc)$/)) {\n // Get source map\n const sourceMapIndex = allAssets.findIndex(([fp]) => fp === filePath + '.map');\n if (sourceMapIndex !== -1) {\n const [sourceMapFilePath, sourceMapAsset] = allAssets.splice(sourceMapIndex, 1)[0];\n Log.log(chalk.gray(sourceMapFilePath), sizeStr(sourceMapAsset.contents));\n }\n }\n }\n });\n\n if (showAdditionalInfo && other.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Files (${other.length}):`);\n\n for (const [filePath, asset] of other.sort((a, b) => a[0].localeCompare(b[0]))) {\n Log.log(filePath, sizeStr(asset.contents));\n }\n }\n\n if (rscEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} React Server Components (${rscEntries.length}):`);\n\n for (const [filePath, assets] of rscEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.rscId!;\n Log.log(\n '/' + (id === '' ? chalk.gray(' (index)') : id),\n sizeStr(assets.contents),\n chalk.gray(filePath)\n );\n }\n }\n\n if (routeEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Static routes (${routeEntries.length}):`);\n\n for (const [, assets] of routeEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.routeId!;\n Log.log('/' + (id === '' ? chalk.gray(' (index)') : id), sizeStr(assets.contents));\n }\n }\n\n if (apiRouteEntries.length) {\n const apiRoutesWithoutSourcemaps = apiRouteEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} API routes (${apiRoutesWithoutSourcemaps.length}):`);\n\n for (const [apiRouteFilename, assets] of apiRoutesWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.apiRouteId!;\n const hasSourceMap = apiRouteEntries.find(\n ([filename, route]) =>\n filename !== apiRouteFilename &&\n route.apiRouteId === assets.apiRouteId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '' ? chalk.gray(' (index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (middlewareEntries.length) {\n const middlewareWithoutSourcemaps = middlewareEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} Middleware:`);\n\n for (const [middlewareFilename, assets] of middlewareWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.middlewareId!;\n const hasSourceMap = middlewareEntries.find(\n ([filename, route]) =>\n filename !== middlewareFilename &&\n route.middlewareId === assets.middlewareId &&\n filename.endsWith('.map')\n );\n Log.log(\n id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (loaderEntries.length) {\n const loadersWithoutSourcemaps = loaderEntries.filter((entry) => !entry[0].endsWith('.map'));\n Log.log('');\n Log.log(chalk.bold`${BLT} Loaders (${loadersWithoutSourcemaps.length}):`);\n\n for (const [loaderFilename, assets] of loadersWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.loaderId!;\n const hasSourceMap = loaderEntries.find(\n ([filename, entry]) =>\n filename !== loaderFilename &&\n entry.loaderId === assets.loaderId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '/' ? '/ ' + chalk.gray('(index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n // Decouple logging from writing for better performance.\n\n await Promise.all(\n [...files.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(async ([file, { contents, targetDomain }]) => {\n // NOTE: Only use `targetDomain` if we have at least one server asset\n const domain = (hasServerOutput && targetDomain) || '';\n const outputPath = path.join(outputDir, domain, file);\n await fs.promises.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.promises.writeFile(outputPath, contents);\n })\n );\n\n Log.log('');\n}\n\nfunction groupBy<T>(array: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n array.forEach((item) => {\n const group = key(item);\n const list = map.get(group) ?? [];\n list.push(item);\n map.set(group, list);\n });\n return map;\n}\n\n// TODO: Move source map modification to the serializer\nexport function getFilesFromSerialAssets(\n resources: SerialAsset[],\n {\n includeSourceMaps,\n files = new Map(),\n platform,\n isServerHosted = platform === 'web',\n }: {\n includeSourceMaps: boolean;\n files?: ExportAssetMap;\n platform?: string;\n isServerHosted?: boolean;\n }\n) {\n resources.forEach((resource) => {\n if (resource.type === 'css-external') {\n return;\n }\n files.set(resource.filename, {\n contents: resource.source,\n originFilename: resource.originFilename,\n targetDomain: isServerHosted ? 'client' : undefined,\n });\n });\n\n return files;\n}\n"],"names":["getFilesFromSerialAssets","persistMetroFilesAsync","bytesFormatter","prettyBytes","bytes","undefined","Intl","NumberFormat","notation","style","unit","unitDisplay","format","toFixed","BLT","files","outputDir","size","fs","promises","mkdir","path","join","recursive","assetEntries","apiRouteEntries","middlewareEntries","routeEntries","rscEntries","loaderEntries","remainingEntries","hasServerOutput","asset","entries","targetDomain","assetId","push","routeId","middlewareId","apiRouteId","rscId","loaderId","groups","groupBy","contentSize","contents","length","Buffer","byteLength","sizeStr","chalk","gray","isExpoRouter","showAdditionalInfo","env","EXPO_DEBUG","assetGroups","sort","a","b","localeCompare","totalAssets","reduce","sum","assets","Log","log","bold","averageContentSize","filter","Boolean","bundles","Map","other","forEach","filepath","match","platform","has","set","get","allAssets","filePath","shift","sourceMapIndex","findIndex","fp","sourceMapFilePath","sourceMapAsset","splice","id","apiRoutesWithoutSourcemaps","route","endsWith","apiRouteFilename","hasSourceMap","find","filename","middlewareWithoutSourcemaps","middlewareFilename","loadersWithoutSourcemaps","entry","loaderFilename","Promise","all","map","file","domain","outputPath","dirname","writeFile","array","key","item","group","list","resources","includeSourceMaps","isServerHosted","resource","type","source","originFilename"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/export/saveAssets.ts"],"sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport type { Platform } from '@expo/config';\nimport type { AssetData } from '@expo/metro/metro';\nimport type { SerialAsset } from '@expo/metro-config/build/serializer/serializerAssets';\nimport chalk from 'chalk';\nimport fs from 'fs';\nimport path from 'path';\n\nimport { Log } from '../log';\nimport { env } from '../utils/env';\n\nlet bytesFormatter: Intl.NumberFormat | undefined | null;\n\nconst prettyBytes = (bytes: number): string => {\n try {\n if (bytesFormatter === undefined && typeof Intl === 'object') {\n bytesFormatter = new Intl.NumberFormat('en', {\n notation: 'compact',\n style: 'unit',\n unit: 'byte',\n unitDisplay: 'narrow',\n });\n }\n if (bytesFormatter != null) {\n return bytesFormatter.format(bytes);\n }\n } catch {\n bytesFormatter = null;\n }\n // Fall back if ICU is unavailable, which is rare but possible with custom Node.js builds\n if (bytes >= 900_000) {\n return `${(bytes / 1_000_000).toFixed(1)}MB`;\n } else if (bytes >= 900) {\n return `${(bytes / 1_000).toFixed(1)}KB`;\n } else {\n return `${bytes}B`;\n }\n};\n\nconst BLT = '\\u203A';\n\nexport type BundleOptions = {\n entryPoint: string;\n platform: Platform;\n dev?: boolean;\n minify?: boolean;\n bytecode: boolean;\n sourceMapUrl?: string;\n sourcemaps?: boolean;\n};\n\nexport type BundleAssetWithFileHashes = AssetData & {\n fileHashes: string[]; // added by the hashAssets asset plugin\n};\n\nexport type BundleOutput = {\n artifacts: SerialAsset[];\n assets: readonly BundleAssetWithFileHashes[];\n};\n\nexport type ManifestAsset = { fileHashes: string[]; files: string[]; hash: string };\n\nexport type Asset = ManifestAsset | BundleAssetWithFileHashes;\n\nexport type ExportAssetDescriptor = {\n contents: string | Buffer;\n originFilename?: string;\n /** An identifier for grouping together variations of the same asset. */\n assetId?: string;\n /** Expo Router route path for formatting the HTML output. */\n routeId?: string;\n /** Expo Router route path for formatting the middleware function output. */\n middlewareId?: string;\n /** Expo Router API route path for formatting the server function output. */\n apiRouteId?: string;\n /** Expo Router route path for formatting the RSC output. */\n rscId?: string;\n /** Expo Router route path for formatting the loader module output. */\n loaderId?: string;\n /** A key for grouping together output files by server- or client-side. */\n targetDomain?: 'server' | 'client';\n};\n\nexport type ExportAssetMap = Map<string, ExportAssetDescriptor>;\n\nexport async function persistMetroFilesAsync(files: ExportAssetMap, outputDir: string) {\n if (!files.size) {\n return;\n }\n await fs.promises.mkdir(path.join(outputDir), { recursive: true });\n\n // Test fixtures:\n // Log.log(\n // JSON.stringify(\n // Object.fromEntries([...files.entries()].map(([k, v]) => [k, { ...v, contents: '' }]))\n // )\n // );\n\n const assetEntries: [string, ExportAssetDescriptor][] = [];\n const apiRouteEntries: [string, ExportAssetDescriptor][] = [];\n const middlewareEntries: [string, ExportAssetDescriptor][] = [];\n const routeEntries: [string, ExportAssetDescriptor][] = [];\n const rscEntries: [string, ExportAssetDescriptor][] = [];\n const loaderEntries: [string, ExportAssetDescriptor][] = [];\n const remainingEntries: [string, ExportAssetDescriptor][] = [];\n\n let hasServerOutput = false;\n for (const asset of files.entries()) {\n hasServerOutput = hasServerOutput || asset[1].targetDomain === 'server';\n if (asset[1].assetId) assetEntries.push(asset);\n else if (asset[1].routeId != null) routeEntries.push(asset);\n else if (asset[1].middlewareId != null) middlewareEntries.push(asset);\n else if (asset[1].apiRouteId != null) apiRouteEntries.push(asset);\n else if (asset[1].rscId != null) rscEntries.push(asset);\n else if (asset[1].loaderId != null) loaderEntries.push(asset);\n else remainingEntries.push(asset);\n }\n\n const groups = groupBy(assetEntries, ([, { assetId }]) => assetId!);\n\n const contentSize = (contents: string | Buffer) => {\n const length =\n typeof contents === 'string' ? Buffer.byteLength(contents, 'utf8') : contents.length;\n return length;\n };\n\n const sizeStr = (contents: string | Buffer) => {\n const length = contentSize(contents);\n const size = chalk.gray`(${prettyBytes(length)})`;\n return size;\n };\n\n // TODO: If any Expo Router is used, then use a new style which is more simple:\n // `chalk.gray(/path/to/) + chalk.cyan('route')`\n // | index.html (1.2kb)\n // | /path\n // | other.html (1.2kb)\n\n const isExpoRouter = routeEntries.length;\n\n // Phase out printing all the assets as users can simply check the file system for more info.\n const showAdditionalInfo = !isExpoRouter || env.EXPO_DEBUG;\n\n const assetGroups = [...groups.entries()].sort((a, b) => a[0].localeCompare(b[0])) as [\n string,\n [string, ExportAssetDescriptor][],\n ][];\n\n if (showAdditionalInfo) {\n if (assetGroups.length) {\n const totalAssets = assetGroups.reduce((sum, [, assets]) => sum + assets.length, 0);\n\n Log.log('');\n Log.log(chalk.bold`${BLT} Assets (${totalAssets}):`);\n\n for (const [assetId, assets] of assetGroups) {\n const averageContentSize =\n assets.reduce((sum, [, { contents }]) => sum + contentSize(contents), 0) / assets.length;\n Log.log(\n assetId,\n chalk.gray(\n `(${[\n assets.length > 1 ? `${assets.length} variations` : '',\n `${prettyBytes(averageContentSize)}`,\n ]\n .filter(Boolean)\n .join(' | ')})`\n )\n );\n }\n }\n }\n\n const bundles: Map<string, [string, ExportAssetDescriptor][]> = new Map();\n const other: [string, ExportAssetDescriptor][] = [];\n\n remainingEntries.forEach(([filepath, asset]) => {\n if (!filepath.match(/_expo\\/(server|static)\\//)) {\n other.push([filepath, asset]);\n } else {\n const platform = filepath.match(/_expo\\/static\\/js\\/([^/]+)\\//)?.[1] ?? 'web';\n if (!bundles.has(platform)) bundles.set(platform, []);\n\n bundles.get(platform)!.push([filepath, asset]);\n }\n });\n\n [...bundles.entries()].forEach(([platform, assets]) => {\n Log.log('');\n Log.log(chalk.bold`${BLT} ${platform} bundles (${assets.length}):`);\n\n const allAssets = assets.sort((a, b) => a[0].localeCompare(b[0]));\n while (allAssets.length) {\n const [filePath, asset] = allAssets.shift()!;\n Log.log(filePath, sizeStr(asset.contents));\n if (filePath.match(/\\.(js|hbc)$/)) {\n // Get source map\n const sourceMapIndex = allAssets.findIndex(([fp]) => fp === filePath + '.map');\n if (sourceMapIndex !== -1) {\n const [sourceMapFilePath, sourceMapAsset] = allAssets.splice(sourceMapIndex, 1)[0];\n Log.log(chalk.gray(sourceMapFilePath), sizeStr(sourceMapAsset.contents));\n }\n }\n }\n });\n\n if (showAdditionalInfo && other.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Files (${other.length}):`);\n\n for (const [filePath, asset] of other.sort((a, b) => a[0].localeCompare(b[0]))) {\n Log.log(filePath, sizeStr(asset.contents));\n }\n }\n\n if (rscEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} React Server Components (${rscEntries.length}):`);\n\n for (const [filePath, assets] of rscEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.rscId!;\n Log.log(\n '/' + (id === '' ? chalk.gray(' (index)') : id),\n sizeStr(assets.contents),\n chalk.gray(filePath)\n );\n }\n }\n\n if (routeEntries.length) {\n Log.log('');\n Log.log(chalk.bold`${BLT} Static routes (${routeEntries.length}):`);\n\n for (const [, assets] of routeEntries.sort((a, b) => a[0].length - b[0].length)) {\n const id = assets.routeId!;\n Log.log('/' + (id === '' ? chalk.gray(' (index)') : id), sizeStr(assets.contents));\n }\n }\n\n if (apiRouteEntries.length) {\n const apiRoutesWithoutSourcemaps = apiRouteEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} API routes (${apiRoutesWithoutSourcemaps.length}):`);\n\n for (const [apiRouteFilename, assets] of apiRoutesWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.apiRouteId!;\n const hasSourceMap = apiRouteEntries.find(\n ([filename, route]) =>\n filename !== apiRouteFilename &&\n route.apiRouteId === assets.apiRouteId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '' ? chalk.gray(' (index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (middlewareEntries.length) {\n const middlewareWithoutSourcemaps = middlewareEntries.filter(\n (route) => !route[0].endsWith('.map')\n );\n Log.log('');\n Log.log(chalk.bold`${BLT} Middleware:`);\n\n for (const [middlewareFilename, assets] of middlewareWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.middlewareId!;\n const hasSourceMap = middlewareEntries.find(\n ([filename, route]) =>\n filename !== middlewareFilename &&\n route.middlewareId === assets.middlewareId &&\n filename.endsWith('.map')\n );\n Log.log(\n id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n if (loaderEntries.length) {\n const loadersWithoutSourcemaps = loaderEntries.filter((entry) => !entry[0].endsWith('.map'));\n Log.log('');\n Log.log(chalk.bold`${BLT} Loaders (${loadersWithoutSourcemaps.length}):`);\n\n for (const [loaderFilename, assets] of loadersWithoutSourcemaps.sort(\n (a, b) => a[0].length - b[0].length\n )) {\n const id = assets.loaderId!;\n const hasSourceMap = loaderEntries.find(\n ([filename, entry]) =>\n filename !== loaderFilename &&\n entry.loaderId === assets.loaderId &&\n filename.endsWith('.map')\n );\n Log.log(\n id === '/' ? '/ ' + chalk.gray('(index)') : id,\n sizeStr(assets.contents),\n hasSourceMap ? chalk.gray(`(source map ${sizeStr(hasSourceMap[1].contents)})`) : ''\n );\n }\n }\n\n // Decouple logging from writing for better performance.\n\n await Promise.all(\n [...files.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(async ([file, { contents, targetDomain }]) => {\n // NOTE: Only use `targetDomain` if we have at least one server asset\n const domain = (hasServerOutput && targetDomain) || '';\n const outputPath = path.join(outputDir, domain, file);\n await fs.promises.mkdir(path.dirname(outputPath), { recursive: true });\n await fs.promises.writeFile(outputPath, contents);\n })\n );\n\n Log.log('');\n}\n\nfunction groupBy<T>(array: T[], key: (item: T) => string): Map<string, T[]> {\n const map = new Map<string, T[]>();\n array.forEach((item) => {\n const group = key(item);\n const list = map.get(group) ?? [];\n list.push(item);\n map.set(group, list);\n });\n return map;\n}\n\n// TODO: Move source map modification to the serializer\nexport function getFilesFromSerialAssets(\n resources: SerialAsset[],\n {\n includeSourceMaps,\n files = new Map(),\n platform,\n isServerHosted = platform === 'web',\n }: {\n includeSourceMaps: boolean;\n files?: ExportAssetMap;\n platform?: string;\n isServerHosted?: boolean;\n }\n) {\n resources.forEach((resource) => {\n if (resource.type === 'css-external') {\n return;\n }\n files.set(resource.filename, {\n contents: resource.source,\n originFilename: resource.originFilename,\n targetDomain: isServerHosted ? 'client' : undefined,\n });\n });\n\n return files;\n}\n"],"names":["getFilesFromSerialAssets","persistMetroFilesAsync","bytesFormatter","prettyBytes","bytes","undefined","Intl","NumberFormat","notation","style","unit","unitDisplay","format","toFixed","BLT","files","outputDir","size","fs","promises","mkdir","path","join","recursive","assetEntries","apiRouteEntries","middlewareEntries","routeEntries","rscEntries","loaderEntries","remainingEntries","hasServerOutput","asset","entries","targetDomain","assetId","push","routeId","middlewareId","apiRouteId","rscId","loaderId","groups","groupBy","contentSize","contents","length","Buffer","byteLength","sizeStr","chalk","gray","isExpoRouter","showAdditionalInfo","env","EXPO_DEBUG","assetGroups","sort","a","b","localeCompare","totalAssets","reduce","sum","assets","Log","log","bold","averageContentSize","filter","Boolean","bundles","Map","other","forEach","filepath","match","platform","has","set","get","allAssets","filePath","shift","sourceMapIndex","findIndex","fp","sourceMapFilePath","sourceMapAsset","splice","id","apiRoutesWithoutSourcemaps","route","endsWith","apiRouteFilename","hasSourceMap","find","filename","middlewareWithoutSourcemaps","middlewareFilename","loadersWithoutSourcemaps","entry","loaderFilename","Promise","all","map","file","domain","outputPath","dirname","writeFile","array","key","item","group","list","resources","includeSourceMaps","isServerHosted","resource","type","source","originFilename"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":""}
|
|
@@ -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
|
-
|
|
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
|
|
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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"}
|
|
@@ -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(
|
|
115
|
+
debug('startSession');
|
|
116
116
|
const resp = await this.protocolClient.sendMessage({
|
|
117
117
|
Request: 'StartSession',
|
|
118
118
|
HostID: pairRecord.HostID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/run/ios/appleDevice/client/LockdowndClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2021 Expo, Inc.\n * Copyright (c) 2018 Drifty Co.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport Debug from 'debug';\nimport { Socket } from 'net';\nimport * as tls from 'tls';\n\nimport { ResponseError, ServiceClient } from './ServiceClient';\nimport { UsbmuxdPairRecord } from './UsbmuxdClient';\nimport { LockdownProtocolClient } from '../protocol/LockdownProtocol';\n\nconst debug = Debug('expo:apple-device:client:lockdownd');\n\nexport interface DeviceValues {\n BasebandCertId: number;\n BasebandKeyHashInformation: {\n AKeyStatus: number;\n SKeyHash: Buffer;\n SKeyStatus: number;\n };\n BasebandSerialNumber: Buffer;\n BasebandVersion: string;\n BoardId: number;\n BuildVersion: string;\n ChipID: number;\n ConnectionType: 'USB' | 'Network';\n DeviceClass: string;\n DeviceColor: string;\n DeviceName: string;\n DieID: number;\n HardwareModel: string;\n HasSiDP: boolean;\n PartitionType: string;\n ProductName: string;\n ProductType: string;\n ProductVersion: string;\n ProductionSOC: boolean;\n ProtocolVersion: string;\n TelephonyCapability: boolean;\n UniqueChipID: number;\n UniqueDeviceID: string;\n WiFiAddress: string;\n [key: string]: any;\n}\n\ninterface LockdowndServiceResponse {\n Request: 'StartService';\n Service: string;\n Port: number;\n EnableServiceSSL?: boolean; // Only on iOS 13+\n}\n\ninterface LockdowndSessionResponse {\n Request: 'StartSession';\n EnableSessionSSL: boolean;\n}\n\ninterface LockdowndAllValuesResponse {\n Request: 'GetValue';\n Value: DeviceValues;\n}\n\ninterface LockdowndValueResponse {\n Request: 'GetValue';\n Key: string;\n Value: string;\n}\n\ninterface LockdowndQueryTypeResponse {\n Request: 'QueryType';\n Type: string;\n}\n\nfunction isLockdowndServiceResponse(resp: any): resp is LockdowndServiceResponse {\n return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;\n}\n\nfunction isLockdowndSessionResponse(resp: any): resp is LockdowndSessionResponse {\n return resp.Request === 'StartSession';\n}\n\nfunction isLockdowndAllValuesResponse(resp: any): resp is LockdowndAllValuesResponse {\n return resp.Request === 'GetValue' && resp.Value !== undefined;\n}\n\nfunction isLockdowndValueResponse(resp: any): resp is LockdowndValueResponse {\n return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';\n}\n\nfunction isLockdowndQueryTypeResponse(resp: any): resp is LockdowndQueryTypeResponse {\n return resp.Request === 'QueryType' && resp.Type !== undefined;\n}\n\nexport class LockdowndClient extends ServiceClient<LockdownProtocolClient> {\n constructor(public socket: Socket) {\n super(socket, new LockdownProtocolClient(socket));\n }\n\n async startService(name: string) {\n debug(`startService: ${name}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartService',\n Service: name,\n });\n\n if (isLockdowndServiceResponse(resp)) {\n return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };\n } else {\n throw new ResponseError(`Error starting service ${name}`, resp);\n }\n }\n\n async startSession(pairRecord: UsbmuxdPairRecord) {\n debug(
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/run/ios/appleDevice/client/LockdowndClient.ts"],"sourcesContent":["/**\n * Copyright (c) 2021 Expo, Inc.\n * Copyright (c) 2018 Drifty Co.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport Debug from 'debug';\nimport { Socket } from 'net';\nimport * as tls from 'tls';\n\nimport { ResponseError, ServiceClient } from './ServiceClient';\nimport { UsbmuxdPairRecord } from './UsbmuxdClient';\nimport { LockdownProtocolClient } from '../protocol/LockdownProtocol';\n\nconst debug = Debug('expo:apple-device:client:lockdownd');\n\nexport interface DeviceValues {\n BasebandCertId: number;\n BasebandKeyHashInformation: {\n AKeyStatus: number;\n SKeyHash: Buffer;\n SKeyStatus: number;\n };\n BasebandSerialNumber: Buffer;\n BasebandVersion: string;\n BoardId: number;\n BuildVersion: string;\n ChipID: number;\n ConnectionType: 'USB' | 'Network';\n DeviceClass: string;\n DeviceColor: string;\n DeviceName: string;\n DieID: number;\n HardwareModel: string;\n HasSiDP: boolean;\n PartitionType: string;\n ProductName: string;\n ProductType: string;\n ProductVersion: string;\n ProductionSOC: boolean;\n ProtocolVersion: string;\n TelephonyCapability: boolean;\n UniqueChipID: number;\n UniqueDeviceID: string;\n WiFiAddress: string;\n [key: string]: any;\n}\n\ninterface LockdowndServiceResponse {\n Request: 'StartService';\n Service: string;\n Port: number;\n EnableServiceSSL?: boolean; // Only on iOS 13+\n}\n\ninterface LockdowndSessionResponse {\n Request: 'StartSession';\n EnableSessionSSL: boolean;\n}\n\ninterface LockdowndAllValuesResponse {\n Request: 'GetValue';\n Value: DeviceValues;\n}\n\ninterface LockdowndValueResponse {\n Request: 'GetValue';\n Key: string;\n Value: string;\n}\n\ninterface LockdowndQueryTypeResponse {\n Request: 'QueryType';\n Type: string;\n}\n\nfunction isLockdowndServiceResponse(resp: any): resp is LockdowndServiceResponse {\n return resp.Request === 'StartService' && resp.Service !== undefined && resp.Port !== undefined;\n}\n\nfunction isLockdowndSessionResponse(resp: any): resp is LockdowndSessionResponse {\n return resp.Request === 'StartSession';\n}\n\nfunction isLockdowndAllValuesResponse(resp: any): resp is LockdowndAllValuesResponse {\n return resp.Request === 'GetValue' && resp.Value !== undefined;\n}\n\nfunction isLockdowndValueResponse(resp: any): resp is LockdowndValueResponse {\n return resp.Request === 'GetValue' && resp.Key !== undefined && typeof resp.Value === 'string';\n}\n\nfunction isLockdowndQueryTypeResponse(resp: any): resp is LockdowndQueryTypeResponse {\n return resp.Request === 'QueryType' && resp.Type !== undefined;\n}\n\nexport class LockdowndClient extends ServiceClient<LockdownProtocolClient> {\n constructor(public socket: Socket) {\n super(socket, new LockdownProtocolClient(socket));\n }\n\n async startService(name: string) {\n debug(`startService: ${name}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartService',\n Service: name,\n });\n\n if (isLockdowndServiceResponse(resp)) {\n return { port: resp.Port, enableServiceSSL: !!resp.EnableServiceSSL };\n } else {\n throw new ResponseError(`Error starting service ${name}`, resp);\n }\n }\n\n async startSession(pairRecord: UsbmuxdPairRecord) {\n debug('startSession');\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'StartSession',\n HostID: pairRecord.HostID,\n SystemBUID: pairRecord.SystemBUID,\n });\n\n if (isLockdowndSessionResponse(resp)) {\n if (resp.EnableSessionSSL) {\n this.protocolClient.socket = new tls.TLSSocket(this.protocolClient.socket, {\n secureContext: tls.createSecureContext({\n // Avoid using `secureProtocol` fixing the socket to a single TLS version.\n // Newer Node versions might not support older TLS versions.\n // By using the default `minVersion` and `maxVersion` options,\n // The socket will automatically use the appropriate TLS version.\n // See: https://nodejs.org/api/tls.html#tlscreatesecurecontextoptions\n cert: pairRecord.RootCertificate,\n key: pairRecord.RootPrivateKey,\n }),\n });\n debug(`Socket upgraded to TLS connection`);\n }\n // TODO: save sessionID for StopSession?\n } else {\n throw new ResponseError('Error starting session', resp);\n }\n }\n\n async getAllValues() {\n debug(`getAllValues`);\n\n const resp = await this.protocolClient.sendMessage({ Request: 'GetValue' });\n\n if (isLockdowndAllValuesResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async getValue(val: string) {\n debug(`getValue: ${val}`);\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'GetValue',\n Key: val,\n });\n\n if (isLockdowndValueResponse(resp)) {\n return resp.Value;\n } else {\n throw new ResponseError('Error getting lockdown value', resp);\n }\n }\n\n async queryType() {\n debug('queryType');\n\n const resp = await this.protocolClient.sendMessage({\n Request: 'QueryType',\n });\n\n if (isLockdowndQueryTypeResponse(resp)) {\n return resp.Type;\n } else {\n throw new ResponseError('Error getting lockdown query type', resp);\n }\n }\n\n async doHandshake(pairRecord: UsbmuxdPairRecord) {\n debug('doHandshake');\n\n // if (await this.lockdownQueryType() !== 'com.apple.mobile.lockdown') {\n // throw new CommandError('Invalid type received from lockdown handshake');\n // }\n // await this.getLockdownValue('ProductVersion');\n // TODO: validate pair and pair\n await this.startSession(pairRecord);\n }\n}\n"],"names":["LockdowndClient","debug","Debug","isLockdowndServiceResponse","resp","Request","Service","undefined","Port","isLockdowndSessionResponse","isLockdowndAllValuesResponse","Value","isLockdowndValueResponse","Key","isLockdowndQueryTypeResponse","Type","ServiceClient","constructor","socket","LockdownProtocolClient","startService","name","protocolClient","sendMessage","port","enableServiceSSL","EnableServiceSSL","ResponseError","startSession","pairRecord","HostID","SystemBUID","EnableSessionSSL","tls","TLSSocket","secureContext","createSecureContext","cert","RootCertificate","key","RootPrivateKey","getAllValues","getValue","val","queryType","doHandshake"],"mappings":"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"}
|