@expo/cli 57.0.6 → 57.0.8
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/static.js +6 -0
- package/build/src/export/static.js.map +1 -0
- 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/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/utils/telemetry/clients/FetchClient.js +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +23 -23
package/build/bin/cli
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/run/android/resolveInstallApkName.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { GradleProps } from './resolveGradlePropsAsync';\nimport type { Device } from '../../start/platforms/android/adb';\nimport { 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 (typeof outputFile === 'string'
|
|
1
|
+
{"version":3,"sources":["../../../../src/run/android/resolveInstallApkName.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport type { GradleProps } from './resolveGradlePropsAsync';\nimport type { Device } from '../../start/platforms/android/adb';\nimport { 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
|
get _assertXcodeBuildResults () {
|
|
13
13
|
return _assertXcodeBuildResults;
|
|
14
14
|
},
|
|
15
|
+
get _extractXcodeBuildErrorLines () {
|
|
16
|
+
return _extractXcodeBuildErrorLines;
|
|
17
|
+
},
|
|
15
18
|
get buildAsync () {
|
|
16
19
|
return buildAsync;
|
|
17
20
|
},
|
|
@@ -435,10 +438,30 @@ function _assertXcodeBuildResults(code, results, error, xcodeProject, logFilePat
|
|
|
435
438
|
if (localizedError) {
|
|
436
439
|
throwWithMessage(_chalk().default.bold(localizedError) + '\n\n');
|
|
437
440
|
}
|
|
441
|
+
// `@expo/xcpretty` can leave a real failure uncounted (its compile-error
|
|
442
|
+
// matching is stateful and anchored, and stderr never passes through it), so
|
|
443
|
+
// the build summary reads "0 error(s)" and in CI the full log below is
|
|
444
|
+
// truncated before the real error line.
|
|
445
|
+
const errorLines = _extractXcodeBuildErrorLines(results + '\n' + error);
|
|
446
|
+
if (errorLines.length) {
|
|
447
|
+
throwWithMessage(_chalk().default.red(errorLines.join('\n')) + '\n\n' + results + '\n\n' + error);
|
|
448
|
+
}
|
|
438
449
|
// Show all the log info because often times the error is coming from a shell script,
|
|
439
450
|
// that invoked a node script, that started metro, which threw an error.
|
|
440
451
|
throwWithMessage(results + '\n\n' + error);
|
|
441
452
|
}
|
|
453
|
+
function _extractXcodeBuildErrorLines(output) {
|
|
454
|
+
const seen = new Set();
|
|
455
|
+
const errors = [];
|
|
456
|
+
for (const raw of output.split(/\r?\n/)){
|
|
457
|
+
const line = raw.trim();
|
|
458
|
+
if (/(?:^|\s)error:\s/.test(line) && !seen.has(line)) {
|
|
459
|
+
seen.add(line);
|
|
460
|
+
errors.push(line);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
return errors;
|
|
464
|
+
}
|
|
442
465
|
function writeBuildLogs(projectRoot, buildOutput, errorOutput) {
|
|
443
466
|
const [logFilePath, errorFilePath] = getErrorLogFilePath(projectRoot);
|
|
444
467
|
_fs().default.writeFileSync(logFilePath, buildOutput);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/run/ios/XcodeBuild.ts"],"sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport { ExpoRunFormatter } from '@expo/xcpretty';\nimport chalk from 'chalk';\nimport type { SpawnOptionsWithoutStdio } from 'child_process';\nimport { spawn } from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { BuildProps, ProjectInfo } from './XcodeBuild.types';\nimport { ensureDeviceIsCodeSignedForDeploymentAsync } from './codeSigning/configureCodeSigning';\nimport { simulatorBuildRequiresCodeSigning } from './codeSigning/simulatorCodeSigning';\nimport * as Log from '../../log';\nimport type { OSType } from '../../start/platforms/ios/simctl';\nimport { ensureDirectory } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { AbortCommandError, CommandError } from '../../utils/errors';\nimport { getUserTerminal } from '../../utils/terminal';\n\n// Error messages that indicate concurrent Xcode build failures.\n// When multiple builds run simultaneously, Xcode's build database can become locked.\nconst CONCURRENT_BUILD_ERROR_MESSAGE_1 = 'database is locked';\nconst CONCURRENT_BUILD_ERROR_MESSAGE_2 = 'there are two concurrent builds running';\n\n/** Get the generic Xcode destination string for a given OS type.\n * Used when building without targeting a specific device (build-only workflow).\n */\nexport function getGenericSimulatorDestination(osType: OSType): string {\n switch (osType) {\n case 'tvOS':\n return 'generic/platform=tvOS Simulator';\n case 'watchOS':\n return 'generic/platform=watchOS Simulator';\n case 'xrOS':\n return 'generic/platform=visionOS Simulator';\n case 'iOS':\n default:\n return 'generic/platform=iOS Simulator';\n }\n}\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 const pathFiltered = appBinaryPathMatch?.filter((a) => typeof a === 'string' && a);\n if (!pathFiltered?.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 = pathFiltered\n .sort((a: string, b: string) => a.length - b.length)[0]\n ?.trim();\n Log.debug(`Found app binary path: ${shortestPath}`);\n return shortestPath ?? null;\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 .map((value) => value[1])\n .filter((value): value is string => !!value);\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;\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 | 'osType'\n | 'isSimulator'\n >\n): Promise<string[]> {\n // Use specific device UDID when available, otherwise use generic simulator destination\n // for build-only workflows (e.g., --device generic).\n const destination = props.device\n ? `id=${props.device.udid}`\n : getGenericSimulatorDestination(props.osType);\n\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 destination,\n\n // Enable parallel code signing for CocoaPods frameworks to speed up device builds.\n // When building for device, multiple frameworks need to be code signed. By default this\n // happens sequentially. This flag allows them to run in parallel.\n // https://github.com/CocoaPods/CocoaPods/pull/6088\n 'COCOAPODS_PARALLEL_CODE_SIGN=true',\n\n // Disable the Xcode compiler index store during CLI builds.\n // The index store is used for code completion, refactoring, and navigation in Xcode IDE.\n // Since CLI builds don't need these features, disabling it saves build time and disk I/O.\n 'COMPILER_INDEX_STORE_ENABLE=NO',\n ];\n\n // Skip code signing setup for generic simulator builds (no device).\n if (\n props.device &&\n (!props.isSimulator || simulatorBuildRequiresCodeSigning(props.projectRoot))\n ) {\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\n if (env.EXPO_PROFILE) {\n args.push('-showBuildTimingSummary');\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 through formatter for display\n for (const line of formatter.pipe(data)) {\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 // Remove extended attributes that can cause code signing failures before building.\n // These are added by Finder, cloud storage services, or when downloading files.\n await removeExtendedAttributesAsync(projectRoot);\n\n const processOptions = getProcessOptions({\n packager: false,\n terminal: getUserTerminal(),\n shouldSkipInitialBundling,\n port,\n eagerBundleOptions,\n });\n\n // Retry logic for concurrent build failures.\n // When multiple Xcode builds run simultaneously (e.g., in CI), the build database\n // can become locked. We retry with exponential backoff to handle this.\n const maxRetries = 3;\n let retryDelaySeconds = 1;\n let lastResults: {\n code: number | null;\n results: string;\n error: string;\n formatter: ExpoRunFormatter;\n } | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const { code, results, formatter, error } = await spawnXcodeBuildWithFormat(\n args,\n processOptions,\n { projectRoot, xcodeProject }\n );\n\n lastResults = { code, results, error, formatter };\n\n // If build succeeded or failed for a reason other than concurrent builds, stop retrying\n if (code === 0 || !isConcurrentBuildError(results)) {\n break;\n }\n\n // If we have retries left, wait and try again\n if (attempt < maxRetries) {\n Log.warn(\n `Xcode build failed due to concurrent builds, retrying in ${retryDelaySeconds}s... (attempt ${attempt + 1}/${maxRetries})`\n );\n await new Promise((resolve) => setTimeout(resolve, retryDelaySeconds * 1000));\n retryDelaySeconds *= 2; // Exponential backoff\n } else {\n Log.warn('Xcode build failed due to concurrent builds after maximum retries.');\n }\n }\n\n const { code, results, formatter, error } = lastResults!;\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\n/**\n * Remove extended attributes that can cause code signing failures.\n *\n * Attributes like `com.apple.FinderInfo` and `com.apple.provenance` are added by Finder,\n * cloud storage services (OneDrive, iCloud, Dropbox), or when files are downloaded.\n * These must be removed before code signing or the build may fail.\n *\n * @see https://developer.apple.com/library/archive/qa/qa1940/_index.html\n */\nasync function removeExtendedAttributesAsync(projectRoot: string): Promise<void> {\n // These specific attributes are known to cause code signing issues.\n // We preserve com.apple.xcode.CreatedByBuildSystem which Xcode uses to manage build directories.\n const attributesToRemove = ['com.apple.FinderInfo', 'com.apple.provenance'];\n\n const iosProjectPath = path.join(projectRoot, 'ios');\n\n // Only proceed if the ios directory exists\n if (!fs.existsSync(iosProjectPath)) {\n return;\n }\n\n for (const attribute of attributesToRemove) {\n try {\n // -r: recursive, -d: delete attribute\n await spawnAsync('xattr', ['-r', '-d', attribute, iosProjectPath]);\n } catch {\n // Ignore errors - attribute may not exist or directory may be missing.\n // This is expected behavior and not a problem.\n Log.debug(`Failed to remove extended attribute ${attribute} (this is usually fine)`);\n }\n }\n}\n\n/**\n * Check if the build failure is due to concurrent Xcode builds.\n * When multiple builds run simultaneously, Xcode's build database can become locked.\n */\nfunction isConcurrentBuildError(results: string): boolean {\n return (\n results.includes(CONCURRENT_BUILD_ERROR_MESSAGE_1) &&\n results.includes(CONCURRENT_BUILD_ERROR_MESSAGE_2)\n );\n}\n"],"names":["_assertXcodeBuildResults","buildAsync","extractEnvVariableFromBuild","getAppBinaryPath","getEscapedPath","getGenericSimulatorDestination","getProcessOptions","getXcodeBuildArgsAsync","logPrettyItem","matchEstimatedBinaryPath","CONCURRENT_BUILD_ERROR_MESSAGE_1","CONCURRENT_BUILD_ERROR_MESSAGE_2","osType","message","Log","log","chalk","buildOutput","appBinaryPathMatch","match","pathFiltered","filter","a","length","CommandError","shortestPath","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","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","destination","device","udid","args","xcodeProject","isWorkspace","name","configuration","scheme","isSimulator","simulatorBuildRequiresCodeSigning","projectRoot","developmentTeamId","ensureDeviceIsCodeSignedForDeploymentAsync","push","buildCache","EXPO_PROFILE","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","removeExtendedAttributesAsync","processOptions","getUserTerminal","maxRetries","retryDelaySeconds","lastResults","attempt","isConcurrentBuildError","warn","setTimeout","logFilePath","writeBuildLogs","wasErrorPresented","errors","errorTitle","throwWithMessage","underline","localizedError","errorOutput","errorFilePath","getErrorLogFilePath","writeFileSync","folder","ensureDirectory","attributesToRemove","iosProjectPath","attribute","spawnAsync","includes"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/run/ios/XcodeBuild.ts"],"sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport { ExpoRunFormatter } from '@expo/xcpretty';\nimport chalk from 'chalk';\nimport type { SpawnOptionsWithoutStdio } from 'child_process';\nimport { spawn } from 'child_process';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\n\nimport type { BuildProps, ProjectInfo } from './XcodeBuild.types';\nimport { ensureDeviceIsCodeSignedForDeploymentAsync } from './codeSigning/configureCodeSigning';\nimport { simulatorBuildRequiresCodeSigning } from './codeSigning/simulatorCodeSigning';\nimport * as Log from '../../log';\nimport type { OSType } from '../../start/platforms/ios/simctl';\nimport { ensureDirectory } from '../../utils/dir';\nimport { env } from '../../utils/env';\nimport { AbortCommandError, CommandError } from '../../utils/errors';\nimport { getUserTerminal } from '../../utils/terminal';\n\n// Error messages that indicate concurrent Xcode build failures.\n// When multiple builds run simultaneously, Xcode's build database can become locked.\nconst CONCURRENT_BUILD_ERROR_MESSAGE_1 = 'database is locked';\nconst CONCURRENT_BUILD_ERROR_MESSAGE_2 = 'there are two concurrent builds running';\n\n/** Get the generic Xcode destination string for a given OS type.\n * Used when building without targeting a specific device (build-only workflow).\n */\nexport function getGenericSimulatorDestination(osType: OSType): string {\n switch (osType) {\n case 'tvOS':\n return 'generic/platform=tvOS Simulator';\n case 'watchOS':\n return 'generic/platform=watchOS Simulator';\n case 'xrOS':\n return 'generic/platform=visionOS Simulator';\n case 'iOS':\n default:\n return 'generic/platform=iOS Simulator';\n }\n}\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 const pathFiltered = appBinaryPathMatch?.filter((a) => typeof a === 'string' && a);\n if (!pathFiltered?.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 = pathFiltered\n .sort((a: string, b: string) => a.length - b.length)[0]\n ?.trim();\n Log.debug(`Found app binary path: ${shortestPath}`);\n return shortestPath ?? null;\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 .map((value) => value[1])\n .filter((value): value is string => !!value);\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;\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 | 'osType'\n | 'isSimulator'\n >\n): Promise<string[]> {\n // Use specific device UDID when available, otherwise use generic simulator destination\n // for build-only workflows (e.g., --device generic).\n const destination = props.device\n ? `id=${props.device.udid}`\n : getGenericSimulatorDestination(props.osType);\n\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 destination,\n\n // Enable parallel code signing for CocoaPods frameworks to speed up device builds.\n // When building for device, multiple frameworks need to be code signed. By default this\n // happens sequentially. This flag allows them to run in parallel.\n // https://github.com/CocoaPods/CocoaPods/pull/6088\n 'COCOAPODS_PARALLEL_CODE_SIGN=true',\n\n // Disable the Xcode compiler index store during CLI builds.\n // The index store is used for code completion, refactoring, and navigation in Xcode IDE.\n // Since CLI builds don't need these features, disabling it saves build time and disk I/O.\n 'COMPILER_INDEX_STORE_ENABLE=NO',\n ];\n\n // Skip code signing setup for generic simulator builds (no device).\n if (\n props.device &&\n (!props.isSimulator || simulatorBuildRequiresCodeSigning(props.projectRoot))\n ) {\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\n if (env.EXPO_PROFILE) {\n args.push('-showBuildTimingSummary');\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 through formatter for display\n for (const line of formatter.pipe(data)) {\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 // Remove extended attributes that can cause code signing failures before building.\n // These are added by Finder, cloud storage services, or when downloading files.\n await removeExtendedAttributesAsync(projectRoot);\n\n const processOptions = getProcessOptions({\n packager: false,\n terminal: getUserTerminal(),\n shouldSkipInitialBundling,\n port,\n eagerBundleOptions,\n });\n\n // Retry logic for concurrent build failures.\n // When multiple Xcode builds run simultaneously (e.g., in CI), the build database\n // can become locked. We retry with exponential backoff to handle this.\n const maxRetries = 3;\n let retryDelaySeconds = 1;\n let lastResults: {\n code: number | null;\n results: string;\n error: string;\n formatter: ExpoRunFormatter;\n } | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const { code, results, formatter, error } = await spawnXcodeBuildWithFormat(\n args,\n processOptions,\n { projectRoot, xcodeProject }\n );\n\n lastResults = { code, results, error, formatter };\n\n // If build succeeded or failed for a reason other than concurrent builds, stop retrying\n if (code === 0 || !isConcurrentBuildError(results)) {\n break;\n }\n\n // If we have retries left, wait and try again\n if (attempt < maxRetries) {\n Log.warn(\n `Xcode build failed due to concurrent builds, retrying in ${retryDelaySeconds}s... (attempt ${attempt + 1}/${maxRetries})`\n );\n await new Promise((resolve) => setTimeout(resolve, retryDelaySeconds * 1000));\n retryDelaySeconds *= 2; // Exponential backoff\n } else {\n Log.warn('Xcode build failed due to concurrent builds after maximum retries.');\n }\n }\n\n const { code, results, formatter, error } = lastResults!;\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\n/**\n * Remove extended attributes that can cause code signing failures.\n *\n * Attributes like `com.apple.FinderInfo` and `com.apple.provenance` are added by Finder,\n * cloud storage services (OneDrive, iCloud, Dropbox), or when files are downloaded.\n * These must be removed before code signing or the build may fail.\n *\n * @see https://developer.apple.com/library/archive/qa/qa1940/_index.html\n */\nasync function removeExtendedAttributesAsync(projectRoot: string): Promise<void> {\n // These specific attributes are known to cause code signing issues.\n // We preserve com.apple.xcode.CreatedByBuildSystem which Xcode uses to manage build directories.\n const attributesToRemove = ['com.apple.FinderInfo', 'com.apple.provenance'];\n\n const iosProjectPath = path.join(projectRoot, 'ios');\n\n // Only proceed if the ios directory exists\n if (!fs.existsSync(iosProjectPath)) {\n return;\n }\n\n for (const attribute of attributesToRemove) {\n try {\n // -r: recursive, -d: delete attribute\n await spawnAsync('xattr', ['-r', '-d', attribute, iosProjectPath]);\n } catch {\n // Ignore errors - attribute may not exist or directory may be missing.\n // This is expected behavior and not a problem.\n Log.debug(`Failed to remove extended attribute ${attribute} (this is usually fine)`);\n }\n }\n}\n\n/**\n * Check if the build failure is due to concurrent Xcode builds.\n * When multiple builds run simultaneously, Xcode's build database can become locked.\n */\nfunction isConcurrentBuildError(results: string): boolean {\n return (\n results.includes(CONCURRENT_BUILD_ERROR_MESSAGE_1) &&\n results.includes(CONCURRENT_BUILD_ERROR_MESSAGE_2)\n );\n}\n"],"names":["_assertXcodeBuildResults","_extractXcodeBuildErrorLines","buildAsync","extractEnvVariableFromBuild","getAppBinaryPath","getEscapedPath","getGenericSimulatorDestination","getProcessOptions","getXcodeBuildArgsAsync","logPrettyItem","matchEstimatedBinaryPath","CONCURRENT_BUILD_ERROR_MESSAGE_1","CONCURRENT_BUILD_ERROR_MESSAGE_2","osType","message","Log","log","chalk","buildOutput","appBinaryPathMatch","match","pathFiltered","filter","a","length","CommandError","shortestPath","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","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","destination","device","udid","args","xcodeProject","isWorkspace","name","configuration","scheme","isSimulator","simulatorBuildRequiresCodeSigning","projectRoot","developmentTeamId","ensureDeviceIsCodeSignedForDeploymentAsync","push","buildCache","EXPO_PROFILE","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","removeExtendedAttributesAsync","processOptions","getUserTerminal","maxRetries","retryDelaySeconds","lastResults","attempt","isConcurrentBuildError","warn","setTimeout","logFilePath","writeBuildLogs","wasErrorPresented","errors","errorTitle","throwWithMessage","underline","localizedError","errorLines","red","output","seen","Set","raw","test","has","add","errorOutput","errorFilePath","getErrorLogFilePath","writeFileSync","folder","ensureDirectory","attributesToRemove","iosProjectPath","attribute","spawnAsync","includes"],"mappings":"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"}
|
|
@@ -29,16 +29,16 @@ function _http() {
|
|
|
29
29
|
};
|
|
30
30
|
return data;
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
const data = /*#__PURE__*/ _interop_require_default(require("http"));
|
|
34
|
-
|
|
32
|
+
function _nodehttp() {
|
|
33
|
+
const data = /*#__PURE__*/ _interop_require_default(require("node:http"));
|
|
34
|
+
_nodehttp = function() {
|
|
35
35
|
return data;
|
|
36
36
|
};
|
|
37
37
|
return data;
|
|
38
38
|
}
|
|
39
|
-
function
|
|
40
|
-
const data = /*#__PURE__*/ _interop_require_default(require("path"));
|
|
41
|
-
|
|
39
|
+
function _nodepath() {
|
|
40
|
+
const data = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
41
|
+
_nodepath = function() {
|
|
42
42
|
return data;
|
|
43
43
|
};
|
|
44
44
|
return data;
|
|
@@ -51,6 +51,7 @@ function _send() {
|
|
|
51
51
|
return data;
|
|
52
52
|
}
|
|
53
53
|
const _log = /*#__PURE__*/ _interop_require_wildcard(require("../log"));
|
|
54
|
+
const _static = require("./static");
|
|
54
55
|
const _dir = require("../utils/dir");
|
|
55
56
|
const _errors = require("../utils/errors");
|
|
56
57
|
const _findUp = require("../utils/findUp");
|
|
@@ -115,7 +116,7 @@ async function serveAsync(inputDir, options) {
|
|
|
115
116
|
throw new _errors.CommandError('Could not start server. Port is not available.');
|
|
116
117
|
}
|
|
117
118
|
options.port = port;
|
|
118
|
-
const serverDist = options.isDefaultDirectory ?
|
|
119
|
+
const serverDist = options.isDefaultDirectory ? _nodepath().default.join(inputDir, 'dist') : inputDir;
|
|
119
120
|
// TODO: `.expo/server/ios`, `.expo/server/android`, etc.
|
|
120
121
|
if (!await (0, _dir.directoryExistsAsync)(serverDist)) {
|
|
121
122
|
throw new _errors.CommandError(`The server directory ${serverDist} does not exist. Run \`npx expo export\` first.`);
|
|
@@ -131,7 +132,8 @@ async function serveAsync(inputDir, options) {
|
|
|
131
132
|
// Detect the type of server we need to setup:
|
|
132
133
|
}
|
|
133
134
|
async function startStaticServerAsync(dist, options) {
|
|
134
|
-
const
|
|
135
|
+
const staticManifest = await (0, _static.loadStaticManifestAsync)(dist);
|
|
136
|
+
const server = _nodehttp().default.createServer((req, res)=>{
|
|
135
137
|
var _req_url;
|
|
136
138
|
// Remove query strings and decode URI
|
|
137
139
|
const filePath = decodeURI(((_req_url = req.url) == null ? void 0 : _req_url.split('?')[0]) ?? '');
|
|
@@ -141,6 +143,16 @@ async function startStaticServerAsync(dist, options) {
|
|
|
141
143
|
extensions: [
|
|
142
144
|
'html'
|
|
143
145
|
]
|
|
146
|
+
}).on('headers', (res, resolvedPath)=>{
|
|
147
|
+
// If `headers` doesn't exist in the manifest, do nothing
|
|
148
|
+
if (!(staticManifest == null ? void 0 : staticManifest.headers)) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
// Headers only apply to page responses and loader data files, never to other static assets.
|
|
152
|
+
if (!resolvedPath.endsWith('.html') && !filePath.startsWith('/_expo/loaders/')) {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
(0, _static.applyStaticHeaders)(res, staticManifest.headers);
|
|
144
156
|
}).on('error', (err)=>{
|
|
145
157
|
if (err.status === 404) {
|
|
146
158
|
res.statusCode = 404;
|
|
@@ -155,8 +167,8 @@ async function startStaticServerAsync(dist, options) {
|
|
|
155
167
|
}
|
|
156
168
|
async function startDynamicServerAsync(dist, options) {
|
|
157
169
|
const middleware = (0, _connect().default)();
|
|
158
|
-
const staticDirectory =
|
|
159
|
-
const serverDirectory =
|
|
170
|
+
const staticDirectory = _nodepath().default.join(dist, 'client');
|
|
171
|
+
const serverDirectory = _nodepath().default.join(dist, 'server');
|
|
160
172
|
const serverHandler = (0, _http().createRequestHandler)({
|
|
161
173
|
build: serverDirectory
|
|
162
174
|
});
|
|
@@ -220,7 +232,7 @@ function canParseURL(url) {
|
|
|
220
232
|
}
|
|
221
233
|
}
|
|
222
234
|
async function isStaticExportAsync(dist) {
|
|
223
|
-
const routesFile =
|
|
235
|
+
const routesFile = _nodepath().default.join(dist, `server/_expo/routes.json`);
|
|
224
236
|
return !await (0, _dir.fileExistsAsync)(routesFile);
|
|
225
237
|
}
|
|
226
238
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/serve/serveAsync.ts"],"sourcesContent":["import chalk from 'chalk';\nimport connect from 'connect';\nimport { createRequestHandler } from 'expo-server/adapter/http';\nimport http from 'http';\nimport path from 'path';\nimport send from 'send';\n\nimport * as Log from '../log';\nimport { directoryExistsAsync, fileExistsAsync } from '../utils/dir';\nimport { CommandError } from '../utils/errors';\nimport { findUpProjectRootOrAssert } from '../utils/findUp';\nimport { setNodeEnv, loadEnvFiles } from '../utils/nodeEnv';\nimport { resolvePortAsync } from '../utils/port';\n\ntype Options = {\n port?: number;\n isDefaultDirectory: boolean;\n};\n\nconst debug = require('debug')('expo:serve') as typeof console.log;\n\n// Start a basic http server\nexport async function serveAsync(inputDir: string, options: Options) {\n const projectRoot = findUpProjectRootOrAssert(inputDir);\n\n setNodeEnv('production');\n loadEnvFiles(projectRoot);\n\n const port = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n fallbackPort: 8081,\n });\n\n if (port == null) {\n throw new CommandError('Could not start server. Port is not available.');\n }\n options.port = port;\n\n const serverDist = options.isDefaultDirectory ? path.join(inputDir, 'dist') : inputDir;\n // TODO: `.expo/server/ios`, `.expo/server/android`, etc.\n\n if (!(await directoryExistsAsync(serverDist))) {\n throw new CommandError(\n `The server directory ${serverDist} does not exist. Run \\`npx expo export\\` first.`\n );\n }\n\n const isStatic = await isStaticExportAsync(serverDist);\n\n Log.log(chalk.dim(`Starting ${isStatic ? 'static ' : ''}server in ${serverDist}`));\n\n if (isStatic) {\n await startStaticServerAsync(serverDist, options);\n } else {\n await startDynamicServerAsync(serverDist, options);\n }\n Log.log(`Server running at http://localhost:${options.port}`);\n // Detect the type of server we need to setup:\n}\n\nasync function startStaticServerAsync(dist: string, options: Options) {\n const server = http.createServer((req, res) => {\n // Remove query strings and decode URI\n const filePath = decodeURI(req.url?.split('?')[0] ?? '');\n\n send(req, filePath, {\n root: dist,\n index: 'index.html',\n extensions: ['html'],\n })\n .on('error', (err: any) => {\n if (err.status === 404) {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n res.statusCode = err.status || 500;\n res.end('Internal Server Error');\n })\n .pipe(res);\n });\n\n server.listen(options.port!);\n}\n\nasync function startDynamicServerAsync(dist: string, options: Options) {\n const middleware = connect();\n\n const staticDirectory = path.join(dist, 'client');\n const serverDirectory = path.join(dist, 'server');\n\n const serverHandler = createRequestHandler({ build: serverDirectory });\n\n // DOM component CORS support\n middleware.use((req, res, next) => {\n // TODO: Only when origin is `file://` (iOS), and Android equivalent.\n\n // Required for DOM components security in release builds.\n\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader(\n 'Access-Control-Allow-Headers',\n 'Origin, X-Requested-With, Content-Type, Accept, expo-platform'\n );\n\n // Handle OPTIONS preflight requests\n if (req.method === 'OPTIONS') {\n res.statusCode = 200;\n res.end();\n return;\n }\n next();\n });\n\n middleware.use((req, res, next) => {\n if (!req?.url || (req.method !== 'GET' && req.method !== 'HEAD')) {\n return next();\n }\n\n const pathname = canParseURL(req.url) ? new URL(req.url).pathname : req.url;\n if (!pathname) {\n return next();\n }\n\n debug(`Maybe serve static:`, pathname);\n\n const stream = send(req, pathname, {\n root: staticDirectory,\n extensions: ['html'],\n });\n\n // add file listener for fallthrough\n let forwardError = false;\n stream.on('file', function onFile() {\n // once file is determined, always forward error\n forwardError = true;\n });\n\n // forward errors\n stream.on('error', function error(err: any) {\n if (forwardError || !(err.statusCode < 500)) {\n next(err);\n return;\n }\n\n next();\n });\n\n // pipe\n stream.pipe(res);\n });\n\n middleware.use(serverHandler);\n\n middleware.listen(options.port!);\n}\n\nfunction canParseURL(url: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isStaticExportAsync(dist: string): Promise<boolean> {\n const routesFile = path.join(dist, `server/_expo/routes.json`);\n return !(await fileExistsAsync(routesFile));\n}\n"],"names":["serveAsync","debug","require","inputDir","options","projectRoot","findUpProjectRootOrAssert","setNodeEnv","loadEnvFiles","port","resolvePortAsync","defaultPort","fallbackPort","CommandError","serverDist","isDefaultDirectory","path","join","directoryExistsAsync","isStatic","isStaticExportAsync","Log","log","chalk","dim","startStaticServerAsync","startDynamicServerAsync","dist","server","http","createServer","req","res","filePath","decodeURI","url","split","send","root","index","extensions","on","err","status","statusCode","end","pipe","listen","middleware","connect","staticDirectory","serverDirectory","serverHandler","createRequestHandler","build","use","next","setHeader","method","pathname","canParseURL","URL","stream","forwardError","onFile","error","routesFile","fileExistsAsync"],"mappings":";;;;+
|
|
1
|
+
{"version":3,"sources":["../../../src/serve/serveAsync.ts"],"sourcesContent":["import chalk from 'chalk';\nimport connect from 'connect';\nimport { createRequestHandler } from 'expo-server/adapter/http';\nimport http from 'node:http';\nimport path from 'node:path';\nimport send from 'send';\n\nimport * as Log from '../log';\nimport { applyStaticHeaders, loadStaticManifestAsync } from './static';\nimport { directoryExistsAsync, fileExistsAsync } from '../utils/dir';\nimport { CommandError } from '../utils/errors';\nimport { findUpProjectRootOrAssert } from '../utils/findUp';\nimport { setNodeEnv, loadEnvFiles } from '../utils/nodeEnv';\nimport { resolvePortAsync } from '../utils/port';\n\ntype Options = {\n port?: number;\n isDefaultDirectory: boolean;\n};\n\nconst debug = require('debug')('expo:serve') as typeof console.log;\n\n// Start a basic http server\nexport async function serveAsync(inputDir: string, options: Options) {\n const projectRoot = findUpProjectRootOrAssert(inputDir);\n\n setNodeEnv('production');\n loadEnvFiles(projectRoot);\n\n const port = await resolvePortAsync(projectRoot, {\n defaultPort: options.port,\n fallbackPort: 8081,\n });\n\n if (port == null) {\n throw new CommandError('Could not start server. Port is not available.');\n }\n options.port = port;\n\n const serverDist = options.isDefaultDirectory ? path.join(inputDir, 'dist') : inputDir;\n // TODO: `.expo/server/ios`, `.expo/server/android`, etc.\n\n if (!(await directoryExistsAsync(serverDist))) {\n throw new CommandError(\n `The server directory ${serverDist} does not exist. Run \\`npx expo export\\` first.`\n );\n }\n\n const isStatic = await isStaticExportAsync(serverDist);\n\n Log.log(chalk.dim(`Starting ${isStatic ? 'static ' : ''}server in ${serverDist}`));\n\n if (isStatic) {\n await startStaticServerAsync(serverDist, options);\n } else {\n await startDynamicServerAsync(serverDist, options);\n }\n Log.log(`Server running at http://localhost:${options.port}`);\n // Detect the type of server we need to setup:\n}\n\nasync function startStaticServerAsync(dist: string, options: Options) {\n const staticManifest = await loadStaticManifestAsync(dist);\n\n const server = http.createServer((req, res) => {\n // Remove query strings and decode URI\n const filePath = decodeURI(req.url?.split('?')[0] ?? '');\n\n send(req, filePath, {\n root: dist,\n index: 'index.html',\n extensions: ['html'],\n })\n .on('headers', (res: http.ServerResponse, resolvedPath: string) => {\n // If `headers` doesn't exist in the manifest, do nothing\n if (!staticManifest?.headers) {\n return;\n }\n // Headers only apply to page responses and loader data files, never to other static assets.\n if (!resolvedPath.endsWith('.html') && !filePath.startsWith('/_expo/loaders/')) {\n return;\n }\n\n applyStaticHeaders(res, staticManifest.headers);\n })\n .on('error', (err: any) => {\n if (err.status === 404) {\n res.statusCode = 404;\n res.end('Not Found');\n return;\n }\n res.statusCode = err.status || 500;\n res.end('Internal Server Error');\n })\n .pipe(res);\n });\n\n server.listen(options.port!);\n}\n\nasync function startDynamicServerAsync(dist: string, options: Options) {\n const middleware = connect();\n\n const staticDirectory = path.join(dist, 'client');\n const serverDirectory = path.join(dist, 'server');\n\n const serverHandler = createRequestHandler({ build: serverDirectory });\n\n // DOM component CORS support\n middleware.use((req, res, next) => {\n // TODO: Only when origin is `file://` (iOS), and Android equivalent.\n\n // Required for DOM components security in release builds.\n\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader(\n 'Access-Control-Allow-Headers',\n 'Origin, X-Requested-With, Content-Type, Accept, expo-platform'\n );\n\n // Handle OPTIONS preflight requests\n if (req.method === 'OPTIONS') {\n res.statusCode = 200;\n res.end();\n return;\n }\n next();\n });\n\n middleware.use((req, res, next) => {\n if (!req?.url || (req.method !== 'GET' && req.method !== 'HEAD')) {\n return next();\n }\n\n const pathname = canParseURL(req.url) ? new URL(req.url).pathname : req.url;\n if (!pathname) {\n return next();\n }\n\n debug(`Maybe serve static:`, pathname);\n\n const stream = send(req, pathname, {\n root: staticDirectory,\n extensions: ['html'],\n });\n\n // add file listener for fallthrough\n let forwardError = false;\n stream.on('file', function onFile() {\n // once file is determined, always forward error\n forwardError = true;\n });\n\n // forward errors\n stream.on('error', function error(err: any) {\n if (forwardError || !(err.statusCode < 500)) {\n next(err);\n return;\n }\n\n next();\n });\n\n // pipe\n stream.pipe(res);\n });\n\n middleware.use(serverHandler);\n\n middleware.listen(options.port!);\n}\n\nfunction canParseURL(url: string): boolean {\n try {\n // eslint-disable-next-line no-new\n new URL(url);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function isStaticExportAsync(dist: string): Promise<boolean> {\n const routesFile = path.join(dist, `server/_expo/routes.json`);\n return !(await fileExistsAsync(routesFile));\n}\n"],"names":["serveAsync","debug","require","inputDir","options","projectRoot","findUpProjectRootOrAssert","setNodeEnv","loadEnvFiles","port","resolvePortAsync","defaultPort","fallbackPort","CommandError","serverDist","isDefaultDirectory","path","join","directoryExistsAsync","isStatic","isStaticExportAsync","Log","log","chalk","dim","startStaticServerAsync","startDynamicServerAsync","dist","staticManifest","loadStaticManifestAsync","server","http","createServer","req","res","filePath","decodeURI","url","split","send","root","index","extensions","on","resolvedPath","headers","endsWith","startsWith","applyStaticHeaders","err","status","statusCode","end","pipe","listen","middleware","connect","staticDirectory","serverDirectory","serverHandler","createRequestHandler","build","use","next","setHeader","method","pathname","canParseURL","URL","stream","forwardError","onFile","error","routesFile","fileExistsAsync"],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
function _export(target, all) {
|
|
6
|
+
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
_export(exports, {
|
|
12
|
+
get applyStaticHeaders () {
|
|
13
|
+
return applyStaticHeaders;
|
|
14
|
+
},
|
|
15
|
+
get loadStaticManifestAsync () {
|
|
16
|
+
return loadStaticManifestAsync;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
function _promises() {
|
|
20
|
+
const data = /*#__PURE__*/ _interop_require_default(require("node:fs/promises"));
|
|
21
|
+
_promises = function() {
|
|
22
|
+
return data;
|
|
23
|
+
};
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
function _nodepath() {
|
|
27
|
+
const data = /*#__PURE__*/ _interop_require_default(require("node:path"));
|
|
28
|
+
_nodepath = function() {
|
|
29
|
+
return data;
|
|
30
|
+
};
|
|
31
|
+
return data;
|
|
32
|
+
}
|
|
33
|
+
function _interop_require_default(obj) {
|
|
34
|
+
return obj && obj.__esModule ? obj : {
|
|
35
|
+
default: obj
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function loadStaticManifestAsync(dist) {
|
|
39
|
+
var _json_redirects;
|
|
40
|
+
let json;
|
|
41
|
+
try {
|
|
42
|
+
json = JSON.parse(await _promises().default.readFile(_nodepath().default.join(dist, '_expo/.routes.json'), 'utf8'));
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
...json,
|
|
48
|
+
redirects: (_json_redirects = json.redirects) == null ? void 0 : _json_redirects.map((rule)=>({
|
|
49
|
+
...rule,
|
|
50
|
+
namedRegex: new RegExp(rule.namedRegex)
|
|
51
|
+
}))
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function applyStaticHeaders(res, headers) {
|
|
55
|
+
for (const [name, value] of Object.entries(headers)){
|
|
56
|
+
if (name.toLowerCase() === 'content-type') {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(value)) {
|
|
60
|
+
for (const headerValue of value){
|
|
61
|
+
res.appendHeader(name, headerValue);
|
|
62
|
+
}
|
|
63
|
+
} else if (!res.hasHeader(name)) {
|
|
64
|
+
res.setHeader(name, value);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//# sourceMappingURL=static.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/serve/static.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport http from 'node:http';\nimport path from 'node:path';\n\nimport type { StaticManifest } from '../export/static';\n\nexport async function loadStaticManifestAsync(\n dist: string\n): Promise<StaticManifest<RegExp> | null> {\n let json: StaticManifest<string>;\n try {\n json = JSON.parse(await fs.readFile(path.join(dist, '_expo/.routes.json'), 'utf8'));\n } catch {\n return null;\n }\n\n return {\n ...json,\n redirects: json.redirects?.map((rule) => ({\n ...rule,\n namedRegex: new RegExp(rule.namedRegex),\n })),\n };\n}\n\n/**\n * Applies headers from a static export manifest to a response, except\n * `Content-Type` which must come from the served file.\n */\nexport function applyStaticHeaders(\n res: http.ServerResponse,\n headers: Record<string, string | string[]>\n): void {\n for (const [name, value] of Object.entries(headers)) {\n if (name.toLowerCase() === 'content-type') {\n continue;\n }\n if (Array.isArray(value)) {\n for (const headerValue of value) {\n res.appendHeader(name, headerValue);\n }\n } else if (!res.hasHeader(name)) {\n res.setHeader(name, value);\n }\n }\n}\n"],"names":["applyStaticHeaders","loadStaticManifestAsync","dist","json","JSON","parse","fs","readFile","path","join","redirects","map","rule","namedRegex","RegExp","res","headers","name","value","Object","entries","toLowerCase","Array","isArray","headerValue","appendHeader","hasHeader","setHeader"],"mappings":";;;;;;;;;;;QA6BgBA;eAAAA;;QAvBMC;eAAAA;;;;gEANP;;;;;;;gEAEE;;;;;;;;;;;AAIV,eAAeA,wBACpBC,IAAY;QAWCC;IATb,IAAIA;IACJ,IAAI;QACFA,OAAOC,KAAKC,KAAK,CAAC,MAAMC,mBAAE,CAACC,QAAQ,CAACC,mBAAI,CAACC,IAAI,CAACP,MAAM,uBAAuB;IAC7E,EAAE,OAAM;QACN,OAAO;IACT;IAEA,OAAO;QACL,GAAGC,IAAI;QACPO,SAAS,GAAEP,kBAAAA,KAAKO,SAAS,qBAAdP,gBAAgBQ,GAAG,CAAC,CAACC,OAAU,CAAA;gBACxC,GAAGA,IAAI;gBACPC,YAAY,IAAIC,OAAOF,KAAKC,UAAU;YACxC,CAAA;IACF;AACF;AAMO,SAASb,mBACde,GAAwB,EACxBC,OAA0C;IAE1C,KAAK,MAAM,CAACC,MAAMC,MAAM,IAAIC,OAAOC,OAAO,CAACJ,SAAU;QACnD,IAAIC,KAAKI,WAAW,OAAO,gBAAgB;YACzC;QACF;QACA,IAAIC,MAAMC,OAAO,CAACL,QAAQ;YACxB,KAAK,MAAMM,eAAeN,MAAO;gBAC/BH,IAAIU,YAAY,CAACR,MAAMO;YACzB;QACF,OAAO,IAAI,CAACT,IAAIW,SAAS,CAACT,OAAO;YAC/BF,IAAIY,SAAS,CAACV,MAAMC;QACtB;IACF;AACF"}
|
|
@@ -26,7 +26,7 @@ class FetchClient {
|
|
|
26
26
|
this.headers = {
|
|
27
27
|
accept: 'application/json',
|
|
28
28
|
'content-type': 'application/json',
|
|
29
|
-
'user-agent': `expo-cli/${"57.0.
|
|
29
|
+
'user-agent': `expo-cli/${"57.0.8"}`,
|
|
30
30
|
authorization: 'Basic ' + _nodebuffer().Buffer.from(`${target}:`).toString('base64')
|
|
31
31
|
};
|
|
32
32
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@expo/cli",
|
|
3
|
-
"version": "57.0.
|
|
3
|
+
"version": "57.0.8",
|
|
4
4
|
"description": "The Expo CLI",
|
|
5
5
|
"main": "main.js",
|
|
6
6
|
"bin": {
|
|
@@ -38,24 +38,24 @@
|
|
|
38
38
|
"homepage": "https://github.com/expo/expo/tree/main/packages/@expo/cli",
|
|
39
39
|
"dependencies": {
|
|
40
40
|
"@expo/code-signing-certificates": "^0.0.6",
|
|
41
|
-
"@expo/config": "~57.0.
|
|
42
|
-
"@expo/config-plugins": "~57.0.
|
|
41
|
+
"@expo/config": "~57.0.5",
|
|
42
|
+
"@expo/config-plugins": "~57.0.5",
|
|
43
43
|
"@expo/devcert": "^1.2.1",
|
|
44
|
-
"@expo/env": "~2.4.
|
|
45
|
-
"@expo/image-utils": "^0.11.
|
|
46
|
-
"@expo/inline-modules": "^0.1.
|
|
47
|
-
"@expo/json-file": "^11.0.
|
|
48
|
-
"@expo/log-box": "^57.0.
|
|
44
|
+
"@expo/env": "~2.4.2",
|
|
45
|
+
"@expo/image-utils": "^0.11.3",
|
|
46
|
+
"@expo/inline-modules": "^0.1.3",
|
|
47
|
+
"@expo/json-file": "^11.0.1",
|
|
48
|
+
"@expo/log-box": "^57.0.1",
|
|
49
49
|
"@expo/metro": "~56.0.0",
|
|
50
|
-
"@expo/metro-config": "~57.0.
|
|
51
|
-
"@expo/metro-file-map": "^57.0.
|
|
52
|
-
"@expo/osascript": "^2.7.
|
|
53
|
-
"@expo/package-manager": "^1.13.
|
|
54
|
-
"@expo/plist": "^0.8.
|
|
55
|
-
"@expo/prebuild-config": "^57.0.
|
|
56
|
-
"@expo/require-utils": "^57.0.
|
|
57
|
-
"@expo/router-server": "^57.0.
|
|
58
|
-
"@expo/schema-utils": "^57.0.
|
|
50
|
+
"@expo/metro-config": "~57.0.5",
|
|
51
|
+
"@expo/metro-file-map": "^57.0.1",
|
|
52
|
+
"@expo/osascript": "^2.7.1",
|
|
53
|
+
"@expo/package-manager": "^1.13.1",
|
|
54
|
+
"@expo/plist": "^0.8.1",
|
|
55
|
+
"@expo/prebuild-config": "^57.0.7",
|
|
56
|
+
"@expo/require-utils": "^57.0.3",
|
|
57
|
+
"@expo/router-server": "^57.0.3",
|
|
58
|
+
"@expo/schema-utils": "^57.0.2",
|
|
59
59
|
"@expo/spawn-async": "^1.8.0",
|
|
60
60
|
"@expo/ws-tunnel": "^2.0.0",
|
|
61
61
|
"@expo/xcpretty": "^4.4.4",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"connect": "^3.7.0",
|
|
72
72
|
"debug": "^4.3.4",
|
|
73
73
|
"dnssd-advertise": "^1.1.4",
|
|
74
|
-
"expo-server": "^57.0.
|
|
74
|
+
"expo-server": "^57.0.1",
|
|
75
75
|
"fetch-nodeshim": "^0.4.10",
|
|
76
76
|
"getenv": "^2.0.0",
|
|
77
77
|
"glob": "^13.0.0",
|
|
@@ -156,13 +156,13 @@
|
|
|
156
156
|
"playwright": "^1.59.0",
|
|
157
157
|
"taskr": "^1.1.0",
|
|
158
158
|
"tree-kill": "^1.2.2",
|
|
159
|
-
"expo": "57.0.4",
|
|
160
159
|
"expo-module-scripts": "56.0.3",
|
|
161
|
-
"expo
|
|
162
|
-
"expo-router": "57.0.
|
|
163
|
-
"
|
|
160
|
+
"@expo/fingerprint": "0.20.5",
|
|
161
|
+
"expo-router": "57.0.6",
|
|
162
|
+
"expo": "57.0.6",
|
|
163
|
+
"expo-modules-autolinking": "57.0.7"
|
|
164
164
|
},
|
|
165
|
-
"gitHead": "
|
|
165
|
+
"gitHead": "b9503d06b8e130abfca1bc16f671dbefb41ad709",
|
|
166
166
|
"scripts": {
|
|
167
167
|
"build": "taskr",
|
|
168
168
|
"clean": "expo-module clean",
|