@expo/cli 55.0.9 → 55.0.10

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.
@@ -40,25 +40,38 @@ async function resolveGradlePropsAsync(projectRoot, options, device) {
40
40
  // NOTE(EvanBacon): Why would this be different? Can we get the different name?
41
41
  const appName = 'app';
42
42
  const apkDirectory = _path().default.join(projectRoot, 'android', appName, 'build', 'outputs', 'apk');
43
- // buildDeveloperTrust -> buildtype: trust, flavors: build, developer
43
+ // buildDeveloperTrust -> buildtype: trust, flavors: buildDeveloper
44
44
  // developmentDebug -> buildType: debug, flavors: development
45
45
  // productionRelease -> buildType: release, flavors: production
46
- // This won't work for non-standard flavor names like "myFlavor" would be treated as "my", "flavor".
47
- const flavors = variant.split(/(?=[A-Z])/).map((v)=>v.toLowerCase());
48
- const buildType = flavors.pop() ?? 'debug';
49
- const apkVariantDirectory = _path().default.join(apkDirectory, ...flavors, buildType);
50
- const architectures = await getConnectedDeviceABIS(buildType, device, options.allArch);
46
+ // previewDebugOptimized -> buildType: debugOptimized, flavors: preview
47
+ const parts = variant.split(/(?=[A-Z])/);
48
+ // Special case: merge 'Optimized' suffix with preceding part, e.g. into 'debugOptimized'
49
+ let buildType = parts.pop() ?? 'debug';
50
+ if (parts.length > 0 && buildType === 'Optimized') {
51
+ buildType = parts.pop().toLowerCase() + buildType;
52
+ } else {
53
+ buildType = buildType.toLowerCase();
54
+ }
55
+ let apkVariantDirectory;
56
+ if (parts.length > 0) {
57
+ const flavorPath = parts[0].toLowerCase() + parts.slice(1).join('');
58
+ apkVariantDirectory = _path().default.join(apkDirectory, flavorPath, buildType);
59
+ } else {
60
+ apkVariantDirectory = _path().default.join(apkDirectory, buildType);
61
+ }
51
62
  return {
52
63
  appName,
53
64
  buildType,
54
- flavors,
65
+ flavors: parts.map((v)=>v.toLowerCase()),
55
66
  apkVariantDirectory,
56
- architectures
67
+ architectures: await getConnectedDeviceABIS(buildType, device, options.allArch)
57
68
  };
58
69
  }
59
70
  async function getConnectedDeviceABIS(buildType, device, allArch) {
60
71
  // Follow the same behavior as iOS, only enable this for debug builds
61
- if (allArch || buildType !== 'debug') {
72
+ // Support both 'debug' and 'debugOptimized' build types
73
+ const isDebugBuild = buildType === 'debug' || buildType === 'debugOptimized';
74
+ if (allArch || !isDebugBuild) {
62
75
  return '';
63
76
  }
64
77
  const abis = await (0, _adb.getDeviceABIsAsync)(device);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/run/android/resolveGradlePropsAsync.ts"],"sourcesContent":["import path from 'path';\n\nimport { Device, getDeviceABIsAsync } from '../../start/platforms/android/adb';\nimport { CommandError } from '../../utils/errors';\n\n// Supported ABIs for Android. see https://developer.android.com/ndk/guides/abis\nconst VALID_ARCHITECTURES = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'];\n\nexport type GradleProps = {\n /** Directory for the APK based on the `variant`. */\n apkVariantDirectory: string;\n /** Name of the app, used in the `apkVariantDirectory`. */\n appName: string;\n /** Last section of the provided `variant`, indicates the starting directory of the file name for the output APK. E.g. \"debug\" or \"release\" */\n buildType: string;\n /** Used to assemble the APK, also included in the output APK filename. */\n flavors?: string[];\n /** Architectures to build for. */\n architectures?: string;\n};\n\nfunction assertVariant(variant?: string) {\n if (variant && typeof variant !== 'string') {\n throw new CommandError('BAD_ARGS', '--variant must be a string');\n }\n return variant ?? 'debug';\n}\n\nexport async function resolveGradlePropsAsync(\n projectRoot: string,\n options: { variant?: string; allArch?: boolean },\n device: Device\n): Promise<GradleProps> {\n const variant = assertVariant(options.variant);\n // NOTE(EvanBacon): Why would this be different? Can we get the different name?\n const appName = 'app';\n\n const apkDirectory = path.join(projectRoot, 'android', appName, 'build', 'outputs', 'apk');\n\n // buildDeveloperTrust -> buildtype: trust, flavors: build, developer\n // developmentDebug -> buildType: debug, flavors: development\n // productionRelease -> buildType: release, flavors: production\n // This won't work for non-standard flavor names like \"myFlavor\" would be treated as \"my\", \"flavor\".\n const flavors = variant.split(/(?=[A-Z])/).map((v) => v.toLowerCase());\n const buildType = flavors.pop() ?? 'debug';\n\n const apkVariantDirectory = path.join(apkDirectory, ...flavors, buildType);\n const architectures = await getConnectedDeviceABIS(buildType, device, options.allArch);\n\n return {\n appName,\n buildType,\n flavors,\n apkVariantDirectory,\n architectures,\n };\n}\n\nasync function getConnectedDeviceABIS(\n buildType: string,\n device: Device,\n allArch?: boolean\n): Promise<string> {\n // Follow the same behavior as iOS, only enable this for debug builds\n if (allArch || buildType !== 'debug') {\n return '';\n }\n\n const abis = await getDeviceABIsAsync(device);\n\n const validAbis = abis.filter((abi) => VALID_ARCHITECTURES.includes(abi));\n return validAbis.filter((abi, i, arr) => arr.indexOf(abi) === i).join(',');\n}\n"],"names":["resolveGradlePropsAsync","VALID_ARCHITECTURES","assertVariant","variant","CommandError","projectRoot","options","device","appName","apkDirectory","path","join","flavors","split","map","v","toLowerCase","buildType","pop","apkVariantDirectory","architectures","getConnectedDeviceABIS","allArch","abis","getDeviceABIsAsync","validAbis","filter","abi","includes","i","arr","indexOf"],"mappings":";;;;+BA4BsBA;;;eAAAA;;;;gEA5BL;;;;;;qBAE0B;wBACd;;;;;;AAE7B,gFAAgF;AAChF,MAAMC,sBAAsB;IAAC;IAAe;IAAa;IAAO;CAAS;AAezE,SAASC,cAAcC,OAAgB;IACrC,IAAIA,WAAW,OAAOA,YAAY,UAAU;QAC1C,MAAM,IAAIC,oBAAY,CAAC,YAAY;IACrC;IACA,OAAOD,WAAW;AACpB;AAEO,eAAeH,wBACpBK,WAAmB,EACnBC,OAAgD,EAChDC,MAAc;IAEd,MAAMJ,UAAUD,cAAcI,QAAQH,OAAO;IAC7C,+EAA+E;IAC/E,MAAMK,UAAU;IAEhB,MAAMC,eAAeC,eAAI,CAACC,IAAI,CAACN,aAAa,WAAWG,SAAS,SAAS,WAAW;IAEpF,qEAAqE;IACrE,6DAA6D;IAC7D,+DAA+D;IAC/D,oGAAoG;IACpG,MAAMI,UAAUT,QAAQU,KAAK,CAAC,aAAaC,GAAG,CAAC,CAACC,IAAMA,EAAEC,WAAW;IACnE,MAAMC,YAAYL,QAAQM,GAAG,MAAM;IAEnC,MAAMC,sBAAsBT,eAAI,CAACC,IAAI,CAACF,iBAAiBG,SAASK;IAChE,MAAMG,gBAAgB,MAAMC,uBAAuBJ,WAAWV,QAAQD,QAAQgB,OAAO;IAErF,OAAO;QACLd;QACAS;QACAL;QACAO;QACAC;IACF;AACF;AAEA,eAAeC,uBACbJ,SAAiB,EACjBV,MAAc,EACde,OAAiB;IAEjB,qEAAqE;IACrE,IAAIA,WAAWL,cAAc,SAAS;QACpC,OAAO;IACT;IAEA,MAAMM,OAAO,MAAMC,IAAAA,uBAAkB,EAACjB;IAEtC,MAAMkB,YAAYF,KAAKG,MAAM,CAAC,CAACC,MAAQ1B,oBAAoB2B,QAAQ,CAACD;IACpE,OAAOF,UAAUC,MAAM,CAAC,CAACC,KAAKE,GAAGC,MAAQA,IAAIC,OAAO,CAACJ,SAASE,GAAGlB,IAAI,CAAC;AACxE"}
1
+ {"version":3,"sources":["../../../../src/run/android/resolveGradlePropsAsync.ts"],"sourcesContent":["import path from 'path';\n\nimport { Device, getDeviceABIsAsync } from '../../start/platforms/android/adb';\nimport { CommandError } from '../../utils/errors';\n\n// Supported ABIs for Android. see https://developer.android.com/ndk/guides/abis\nconst VALID_ARCHITECTURES = ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'];\n\nexport type GradleProps = {\n /** Directory for the APK based on the `variant`. */\n apkVariantDirectory: string;\n /** Name of the app, used in the `apkVariantDirectory`. */\n appName: string;\n /** Last section of the provided `variant`, indicates the starting directory of the file name for the output APK. E.g. \"debug\" or \"release\" */\n buildType: string;\n /** Used to assemble the APK, also included in the output APK filename. */\n flavors?: string[];\n /** Architectures to build for. */\n architectures?: string;\n};\n\nfunction assertVariant(variant?: string) {\n if (variant && typeof variant !== 'string') {\n throw new CommandError('BAD_ARGS', '--variant must be a string');\n }\n return variant ?? 'debug';\n}\n\nexport async function resolveGradlePropsAsync(\n projectRoot: string,\n options: { variant?: string; allArch?: boolean },\n device: Device\n): Promise<GradleProps> {\n const variant = assertVariant(options.variant);\n // NOTE(EvanBacon): Why would this be different? Can we get the different name?\n const appName = 'app';\n\n const apkDirectory = path.join(projectRoot, 'android', appName, 'build', 'outputs', 'apk');\n\n // buildDeveloperTrust -> buildtype: trust, flavors: buildDeveloper\n // developmentDebug -> buildType: debug, flavors: development\n // productionRelease -> buildType: release, flavors: production\n // previewDebugOptimized -> buildType: debugOptimized, flavors: preview\n const parts = variant.split(/(?=[A-Z])/);\n\n // Special case: merge 'Optimized' suffix with preceding part, e.g. into 'debugOptimized'\n let buildType = parts.pop() ?? 'debug';\n if (parts.length > 0 && buildType === 'Optimized') {\n buildType = parts.pop()!.toLowerCase() + buildType;\n } else {\n buildType = buildType.toLowerCase();\n }\n\n let apkVariantDirectory: string;\n if (parts.length > 0) {\n const flavorPath = parts[0].toLowerCase() + parts.slice(1).join('');\n apkVariantDirectory = path.join(apkDirectory, flavorPath, buildType);\n } else {\n apkVariantDirectory = path.join(apkDirectory, buildType);\n }\n\n return {\n appName,\n buildType,\n flavors: parts.map((v) => v.toLowerCase()),\n apkVariantDirectory,\n architectures: await getConnectedDeviceABIS(buildType, device, options.allArch),\n };\n}\n\nasync function getConnectedDeviceABIS(\n buildType: string,\n device: Device,\n allArch?: boolean\n): Promise<string> {\n // Follow the same behavior as iOS, only enable this for debug builds\n // Support both 'debug' and 'debugOptimized' build types\n const isDebugBuild = buildType === 'debug' || buildType === 'debugOptimized';\n if (allArch || !isDebugBuild) {\n return '';\n }\n\n const abis = await getDeviceABIsAsync(device);\n\n const validAbis = abis.filter((abi) => VALID_ARCHITECTURES.includes(abi));\n return validAbis.filter((abi, i, arr) => arr.indexOf(abi) === i).join(',');\n}\n"],"names":["resolveGradlePropsAsync","VALID_ARCHITECTURES","assertVariant","variant","CommandError","projectRoot","options","device","appName","apkDirectory","path","join","parts","split","buildType","pop","length","toLowerCase","apkVariantDirectory","flavorPath","slice","flavors","map","v","architectures","getConnectedDeviceABIS","allArch","isDebugBuild","abis","getDeviceABIsAsync","validAbis","filter","abi","includes","i","arr","indexOf"],"mappings":";;;;+BA4BsBA;;;eAAAA;;;;gEA5BL;;;;;;qBAE0B;wBACd;;;;;;AAE7B,gFAAgF;AAChF,MAAMC,sBAAsB;IAAC;IAAe;IAAa;IAAO;CAAS;AAezE,SAASC,cAAcC,OAAgB;IACrC,IAAIA,WAAW,OAAOA,YAAY,UAAU;QAC1C,MAAM,IAAIC,oBAAY,CAAC,YAAY;IACrC;IACA,OAAOD,WAAW;AACpB;AAEO,eAAeH,wBACpBK,WAAmB,EACnBC,OAAgD,EAChDC,MAAc;IAEd,MAAMJ,UAAUD,cAAcI,QAAQH,OAAO;IAC7C,+EAA+E;IAC/E,MAAMK,UAAU;IAEhB,MAAMC,eAAeC,eAAI,CAACC,IAAI,CAACN,aAAa,WAAWG,SAAS,SAAS,WAAW;IAEpF,mEAAmE;IACnE,6DAA6D;IAC7D,+DAA+D;IAC/D,uEAAuE;IACvE,MAAMI,QAAQT,QAAQU,KAAK,CAAC;IAE5B,yFAAyF;IACzF,IAAIC,YAAYF,MAAMG,GAAG,MAAM;IAC/B,IAAIH,MAAMI,MAAM,GAAG,KAAKF,cAAc,aAAa;QACjDA,YAAYF,MAAMG,GAAG,GAAIE,WAAW,KAAKH;IAC3C,OAAO;QACLA,YAAYA,UAAUG,WAAW;IACnC;IAEA,IAAIC;IACJ,IAAIN,MAAMI,MAAM,GAAG,GAAG;QACpB,MAAMG,aAAaP,KAAK,CAAC,EAAE,CAACK,WAAW,KAAKL,MAAMQ,KAAK,CAAC,GAAGT,IAAI,CAAC;QAChEO,sBAAsBR,eAAI,CAACC,IAAI,CAACF,cAAcU,YAAYL;IAC5D,OAAO;QACLI,sBAAsBR,eAAI,CAACC,IAAI,CAACF,cAAcK;IAChD;IAEA,OAAO;QACLN;QACAM;QACAO,SAAST,MAAMU,GAAG,CAAC,CAACC,IAAMA,EAAEN,WAAW;QACvCC;QACAM,eAAe,MAAMC,uBAAuBX,WAAWP,QAAQD,QAAQoB,OAAO;IAChF;AACF;AAEA,eAAeD,uBACbX,SAAiB,EACjBP,MAAc,EACdmB,OAAiB;IAEjB,qEAAqE;IACrE,wDAAwD;IACxD,MAAMC,eAAeb,cAAc,WAAWA,cAAc;IAC5D,IAAIY,WAAW,CAACC,cAAc;QAC5B,OAAO;IACT;IAEA,MAAMC,OAAO,MAAMC,IAAAA,uBAAkB,EAACtB;IAEtC,MAAMuB,YAAYF,KAAKG,MAAM,CAAC,CAACC,MAAQ/B,oBAAoBgC,QAAQ,CAACD;IACpE,OAAOF,UAAUC,MAAM,CAAC,CAACC,KAAKE,GAAGC,MAAQA,IAAIC,OAAO,CAACJ,SAASE,GAAGvB,IAAI,CAAC;AACxE"}
@@ -92,20 +92,22 @@ class DevServerManagerActions {
92
92
  })}`);
93
93
  rows--;
94
94
  }
95
- const qr = (0, _qr.printQRCode)(interstitialPageUrl ?? nativeRuntimeUrl);
96
- rows -= qr.lines;
97
- qr.print();
98
- let qrMessage = '';
99
- if (!options.devClient) {
100
- qrMessage = `Scan the QR code above to open in ${(0, _chalk().default)`{bold Expo Go}`}.`;
101
- } else {
102
- qrMessage = (0, _chalk().default)`Scan the QR code above to open in a {bold development build}.`;
103
- qrMessage += ` (${(0, _link.learnMore)('https://expo.fyi/start')})`;
95
+ if (!_env.env.EXPO_NO_QR_CODE) {
96
+ const qr = (0, _qr.printQRCode)(interstitialPageUrl ?? nativeRuntimeUrl);
97
+ rows -= qr.lines;
98
+ qr.print();
99
+ let qrMessage = '';
100
+ if (!options.devClient) {
101
+ qrMessage = `Scan the QR code above to open in ${(0, _chalk().default)`{bold Expo Go}`}.`;
102
+ } else {
103
+ qrMessage = (0, _chalk().default)`Scan the QR code above to open in a {bold development build}.`;
104
+ qrMessage += ` (${(0, _link.learnMore)('https://expo.fyi/start')})`;
105
+ }
106
+ rows--;
107
+ _log.log((0, _commandsTable.printItem)(qrMessage, {
108
+ dim: true
109
+ }));
104
110
  }
105
- rows--;
106
- _log.log((0, _commandsTable.printItem)(qrMessage, {
107
- dim: true
108
- }));
109
111
  if (interstitialPageUrl) {
110
112
  rows--;
111
113
  _log.log((0, _commandsTable.printItem)((0, _chalk().default)`Choose an app to open your project at {underline ${interstitialPageUrl}}`));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/interface/interactiveActions.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { BLT, printHelp, printItem, printUsage, StartOptions } from './commandsTable';\nimport { createDevToolsMenuItems } from './createDevToolsMenuItems';\nimport * as Log from '../../log';\nimport { env } from '../../utils/env';\nimport { learnMore } from '../../utils/link';\nimport { ExpoChoice, selectAsync } from '../../utils/prompts';\nimport { printQRCode } from '../../utils/qr';\nimport { DevServerManager } from '../server/DevServerManager';\nimport {\n openJsInspector,\n queryAllInspectorAppsAsync,\n promptInspectorAppAsync,\n} from '../server/middleware/inspector/JsInspector';\n\nconst debug = require('debug')('expo:start:interface:interactiveActions') as typeof console.log;\n\ninterface MoreToolMenuItem extends ExpoChoice<string> {\n action?: () => unknown;\n}\n\n/** Wraps the DevServerManager and adds an interface for user actions. */\nexport class DevServerManagerActions {\n constructor(\n private devServerManager: DevServerManager,\n private options: Pick<StartOptions, 'devClient' | 'platforms'>\n ) {}\n\n printDevServerInfo(\n options: Pick<StartOptions, 'devClient' | 'isWebSocketsEnabled' | 'platforms'>\n ) {\n // Keep track of approximately how much space we have to print our usage guide\n let rows = process.stdout.rows || Infinity;\n\n // If native dev server is running, print its URL.\n if (this.devServerManager.getNativeDevServerPort()) {\n const devServer = this.devServerManager.getDefaultDevServer();\n try {\n const nativeRuntimeUrl = devServer.getNativeRuntimeUrl()!;\n const interstitialPageUrl = devServer.getRedirectUrl();\n\n // Print the URL to stdout for tests\n if (env.__EXPO_E2E_TEST) {\n console.info(\n `[__EXPO_E2E_TEST:server] ${JSON.stringify({ url: devServer.getDevServerUrl() })}`\n );\n rows--;\n }\n\n const qr = printQRCode(interstitialPageUrl ?? nativeRuntimeUrl);\n rows -= qr.lines;\n qr.print();\n\n let qrMessage = '';\n if (!options.devClient) {\n qrMessage = `Scan the QR code above to open in ${chalk`{bold Expo Go}`}.`;\n } else {\n qrMessage = chalk`Scan the QR code above to open in a {bold development build}.`;\n qrMessage += ` (${learnMore('https://expo.fyi/start')})`;\n }\n rows--;\n Log.log(printItem(qrMessage, { dim: true }));\n\n if (interstitialPageUrl) {\n rows--;\n Log.log(\n printItem(\n chalk`Choose an app to open your project at {underline ${interstitialPageUrl}}`\n )\n );\n }\n\n rows--;\n Log.log(printItem(chalk`Metro: {underline ${nativeRuntimeUrl}}`));\n } catch (error) {\n console.log('err', error);\n // @ts-ignore: If there is no development build scheme, then skip the QR code.\n if (error.code !== 'NO_DEV_CLIENT_SCHEME') {\n throw error;\n } else {\n const serverUrl = devServer.getDevServerUrl();\n Log.log(printItem(chalk`Metro: {underline ${serverUrl}}`));\n Log.log(printItem(`Linking is disabled because the client scheme cannot be resolved.`));\n rows -= 2;\n }\n }\n }\n\n if (this.options.platforms?.includes('web')) {\n const webDevServer = this.devServerManager.getWebDevServer();\n const webUrl = webDevServer?.getDevServerUrl({ hostType: 'localhost' });\n if (webUrl) {\n Log.log(printItem(chalk`Web: {underline ${webUrl}}`));\n rows--;\n }\n }\n\n printUsage(options, { verbose: false, rows });\n printHelp();\n Log.log();\n }\n\n async openJsInspectorAsync() {\n try {\n const metroServerOrigin = this.devServerManager.getDefaultDevServer().getJsInspectorBaseUrl();\n const apps = await queryAllInspectorAppsAsync(metroServerOrigin);\n if (!apps.length) {\n return Log.warn(\n chalk`{bold Debug:} No compatible apps connected, React Native DevTools can only be used with Hermes. ${learnMore(\n 'https://docs.expo.dev/guides/using-hermes/'\n )}`\n );\n }\n\n const app = await promptInspectorAppAsync(apps);\n if (!app) {\n return Log.error(chalk`{bold Debug:} No inspectable device selected`);\n }\n\n if (!(await openJsInspector(metroServerOrigin, app))) {\n Log.warn(\n chalk`{bold Debug:} Failed to open the React Native DevTools, see debug logs for more info.`\n );\n }\n } catch (error: any) {\n // Handle aborting prompt\n if (error.code === 'ABORTED') return;\n\n Log.error('Failed to open the React Native DevTools.');\n Log.exception(error);\n }\n }\n\n reloadApp() {\n Log.log(`${BLT} Reloading apps`);\n // Send reload requests over the dev servers\n this.devServerManager.broadcastMessage('reload');\n }\n\n async openMoreToolsAsync() {\n // Options match: Chrome > View > Developer\n try {\n const defaultMenuItems: MoreToolMenuItem[] = [\n { title: 'Inspect elements', value: 'toggleElementInspector' },\n { title: 'Toggle performance monitor', value: 'togglePerformanceMonitor' },\n { title: 'Toggle developer menu', value: 'toggleDevMenu' },\n { title: 'Reload app', value: 'reload' },\n // TODO: Maybe a \"View Source\" option to open code.\n ];\n\n const defaultServerUrl = this.devServerManager\n .getDefaultDevServer()\n .getUrlCreator()\n .constructUrl({ scheme: 'http' });\n\n const metroServerOrigin = this.devServerManager.getDefaultDevServer().getJsInspectorBaseUrl();\n const plugins = await this.devServerManager.devtoolsPluginManager.queryPluginsAsync();\n\n const menuItems = [\n ...defaultMenuItems,\n ...createDevToolsMenuItems(plugins, defaultServerUrl, metroServerOrigin),\n ];\n\n const value = await selectAsync(chalk`Dev tools {dim (native only)}`, menuItems);\n const menuItem = menuItems.find((item) => item.value === value);\n if (menuItem?.action) {\n menuItem.action();\n } else if (menuItem?.value) {\n this.devServerManager.broadcastMessage('sendDevCommand', { name: menuItem.value });\n }\n } catch (error: any) {\n debug(error);\n // do nothing\n } finally {\n printHelp();\n }\n }\n\n toggleDevMenu() {\n Log.log(`${BLT} Toggling dev menu`);\n this.devServerManager.broadcastMessage('devMenu');\n }\n}\n"],"names":["DevServerManagerActions","debug","require","constructor","devServerManager","options","printDevServerInfo","rows","process","stdout","Infinity","getNativeDevServerPort","devServer","getDefaultDevServer","nativeRuntimeUrl","getNativeRuntimeUrl","interstitialPageUrl","getRedirectUrl","env","__EXPO_E2E_TEST","console","info","JSON","stringify","url","getDevServerUrl","qr","printQRCode","lines","print","qrMessage","devClient","chalk","learnMore","Log","log","printItem","dim","error","code","serverUrl","platforms","includes","webDevServer","getWebDevServer","webUrl","hostType","printUsage","verbose","printHelp","openJsInspectorAsync","metroServerOrigin","getJsInspectorBaseUrl","apps","queryAllInspectorAppsAsync","length","warn","app","promptInspectorAppAsync","openJsInspector","exception","reloadApp","BLT","broadcastMessage","openMoreToolsAsync","defaultMenuItems","title","value","defaultServerUrl","getUrlCreator","constructUrl","scheme","plugins","devtoolsPluginManager","queryPluginsAsync","menuItems","createDevToolsMenuItems","selectAsync","menuItem","find","item","action","name","toggleDevMenu"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/start/interface/interactiveActions.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { BLT, printHelp, printItem, printUsage, StartOptions } from './commandsTable';\nimport { createDevToolsMenuItems } from './createDevToolsMenuItems';\nimport * as Log from '../../log';\nimport { env } from '../../utils/env';\nimport { learnMore } from '../../utils/link';\nimport { ExpoChoice, selectAsync } from '../../utils/prompts';\nimport { printQRCode } from '../../utils/qr';\nimport { DevServerManager } from '../server/DevServerManager';\nimport {\n openJsInspector,\n queryAllInspectorAppsAsync,\n promptInspectorAppAsync,\n} from '../server/middleware/inspector/JsInspector';\n\nconst debug = require('debug')('expo:start:interface:interactiveActions') as typeof console.log;\n\ninterface MoreToolMenuItem extends ExpoChoice<string> {\n action?: () => unknown;\n}\n\n/** Wraps the DevServerManager and adds an interface for user actions. */\nexport class DevServerManagerActions {\n constructor(\n private devServerManager: DevServerManager,\n private options: Pick<StartOptions, 'devClient' | 'platforms'>\n ) {}\n\n printDevServerInfo(\n options: Pick<StartOptions, 'devClient' | 'isWebSocketsEnabled' | 'platforms'>\n ) {\n // Keep track of approximately how much space we have to print our usage guide\n let rows = process.stdout.rows || Infinity;\n\n // If native dev server is running, print its URL.\n if (this.devServerManager.getNativeDevServerPort()) {\n const devServer = this.devServerManager.getDefaultDevServer();\n try {\n const nativeRuntimeUrl = devServer.getNativeRuntimeUrl()!;\n const interstitialPageUrl = devServer.getRedirectUrl();\n\n // Print the URL to stdout for tests\n if (env.__EXPO_E2E_TEST) {\n console.info(\n `[__EXPO_E2E_TEST:server] ${JSON.stringify({ url: devServer.getDevServerUrl() })}`\n );\n rows--;\n }\n\n if (!env.EXPO_NO_QR_CODE) {\n const qr = printQRCode(interstitialPageUrl ?? nativeRuntimeUrl);\n rows -= qr.lines;\n qr.print();\n\n let qrMessage = '';\n if (!options.devClient) {\n qrMessage = `Scan the QR code above to open in ${chalk`{bold Expo Go}`}.`;\n } else {\n qrMessage = chalk`Scan the QR code above to open in a {bold development build}.`;\n qrMessage += ` (${learnMore('https://expo.fyi/start')})`;\n }\n rows--;\n Log.log(printItem(qrMessage, { dim: true }));\n }\n\n if (interstitialPageUrl) {\n rows--;\n Log.log(\n printItem(\n chalk`Choose an app to open your project at {underline ${interstitialPageUrl}}`\n )\n );\n }\n\n rows--;\n Log.log(printItem(chalk`Metro: {underline ${nativeRuntimeUrl}}`));\n } catch (error) {\n console.log('err', error);\n // @ts-ignore: If there is no development build scheme, then skip the QR code.\n if (error.code !== 'NO_DEV_CLIENT_SCHEME') {\n throw error;\n } else {\n const serverUrl = devServer.getDevServerUrl();\n Log.log(printItem(chalk`Metro: {underline ${serverUrl}}`));\n Log.log(printItem(`Linking is disabled because the client scheme cannot be resolved.`));\n rows -= 2;\n }\n }\n }\n\n if (this.options.platforms?.includes('web')) {\n const webDevServer = this.devServerManager.getWebDevServer();\n const webUrl = webDevServer?.getDevServerUrl({ hostType: 'localhost' });\n if (webUrl) {\n Log.log(printItem(chalk`Web: {underline ${webUrl}}`));\n rows--;\n }\n }\n\n printUsage(options, { verbose: false, rows });\n printHelp();\n Log.log();\n }\n\n async openJsInspectorAsync() {\n try {\n const metroServerOrigin = this.devServerManager.getDefaultDevServer().getJsInspectorBaseUrl();\n const apps = await queryAllInspectorAppsAsync(metroServerOrigin);\n if (!apps.length) {\n return Log.warn(\n chalk`{bold Debug:} No compatible apps connected, React Native DevTools can only be used with Hermes. ${learnMore(\n 'https://docs.expo.dev/guides/using-hermes/'\n )}`\n );\n }\n\n const app = await promptInspectorAppAsync(apps);\n if (!app) {\n return Log.error(chalk`{bold Debug:} No inspectable device selected`);\n }\n\n if (!(await openJsInspector(metroServerOrigin, app))) {\n Log.warn(\n chalk`{bold Debug:} Failed to open the React Native DevTools, see debug logs for more info.`\n );\n }\n } catch (error: any) {\n // Handle aborting prompt\n if (error.code === 'ABORTED') return;\n\n Log.error('Failed to open the React Native DevTools.');\n Log.exception(error);\n }\n }\n\n reloadApp() {\n Log.log(`${BLT} Reloading apps`);\n // Send reload requests over the dev servers\n this.devServerManager.broadcastMessage('reload');\n }\n\n async openMoreToolsAsync() {\n // Options match: Chrome > View > Developer\n try {\n const defaultMenuItems: MoreToolMenuItem[] = [\n { title: 'Inspect elements', value: 'toggleElementInspector' },\n { title: 'Toggle performance monitor', value: 'togglePerformanceMonitor' },\n { title: 'Toggle developer menu', value: 'toggleDevMenu' },\n { title: 'Reload app', value: 'reload' },\n // TODO: Maybe a \"View Source\" option to open code.\n ];\n\n const defaultServerUrl = this.devServerManager\n .getDefaultDevServer()\n .getUrlCreator()\n .constructUrl({ scheme: 'http' });\n\n const metroServerOrigin = this.devServerManager.getDefaultDevServer().getJsInspectorBaseUrl();\n const plugins = await this.devServerManager.devtoolsPluginManager.queryPluginsAsync();\n\n const menuItems = [\n ...defaultMenuItems,\n ...createDevToolsMenuItems(plugins, defaultServerUrl, metroServerOrigin),\n ];\n\n const value = await selectAsync(chalk`Dev tools {dim (native only)}`, menuItems);\n const menuItem = menuItems.find((item) => item.value === value);\n if (menuItem?.action) {\n menuItem.action();\n } else if (menuItem?.value) {\n this.devServerManager.broadcastMessage('sendDevCommand', { name: menuItem.value });\n }\n } catch (error: any) {\n debug(error);\n // do nothing\n } finally {\n printHelp();\n }\n }\n\n toggleDevMenu() {\n Log.log(`${BLT} Toggling dev menu`);\n this.devServerManager.broadcastMessage('devMenu');\n }\n}\n"],"names":["DevServerManagerActions","debug","require","constructor","devServerManager","options","printDevServerInfo","rows","process","stdout","Infinity","getNativeDevServerPort","devServer","getDefaultDevServer","nativeRuntimeUrl","getNativeRuntimeUrl","interstitialPageUrl","getRedirectUrl","env","__EXPO_E2E_TEST","console","info","JSON","stringify","url","getDevServerUrl","EXPO_NO_QR_CODE","qr","printQRCode","lines","print","qrMessage","devClient","chalk","learnMore","Log","log","printItem","dim","error","code","serverUrl","platforms","includes","webDevServer","getWebDevServer","webUrl","hostType","printUsage","verbose","printHelp","openJsInspectorAsync","metroServerOrigin","getJsInspectorBaseUrl","apps","queryAllInspectorAppsAsync","length","warn","app","promptInspectorAppAsync","openJsInspector","exception","reloadApp","BLT","broadcastMessage","openMoreToolsAsync","defaultMenuItems","title","value","defaultServerUrl","getUrlCreator","constructUrl","scheme","plugins","devtoolsPluginManager","queryPluginsAsync","menuItems","createDevToolsMenuItems","selectAsync","menuItem","find","item","action","name","toggleDevMenu"],"mappings":"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"}
@@ -12,6 +12,9 @@ _export(exports, {
12
12
  MetroTerminalReporter: function() {
13
13
  return MetroTerminalReporter;
14
14
  },
15
+ event: function() {
16
+ return event;
17
+ },
15
18
  extractCodeFrame: function() {
16
19
  return extractCodeFrame;
17
20
  },
@@ -52,20 +55,35 @@ const _env = require("../../../utils/env");
52
55
  const _link = require("../../../utils/link");
53
56
  const _serverLogLikeMetro = require("../serverLogLikeMetro");
54
57
  const _metroErrorInterface = require("./metroErrorInterface");
58
+ const _events = require("../../../events");
59
+ const _ansi = require("../../../utils/ansi");
55
60
  function _interop_require_default(obj) {
56
61
  return obj && obj.__esModule ? obj : {
57
62
  default: obj
58
63
  };
59
64
  }
60
65
  const debug = require('debug')('expo:metro:logger');
66
+ const event = (0, _events.events)('metro', (t)=>[
67
+ t.event(),
68
+ t.event(),
69
+ t.event(),
70
+ t.event(),
71
+ t.event(),
72
+ t.event(),
73
+ t.event(),
74
+ t.event(),
75
+ t.event()
76
+ ]);
61
77
  const MAX_PROGRESS_BAR_CHAR_WIDTH = 16;
62
78
  const DARK_BLOCK_CHAR = '\u2593';
63
79
  const LIGHT_BLOCK_CHAR = '\u2591';
64
80
  class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
65
- constructor(projectRoot, terminal){
66
- super(terminal), this.projectRoot = projectRoot;
81
+ #lastFailedBuildID;
82
+ constructor(serverRoot, terminal){
83
+ super(terminal), this.serverRoot = serverRoot;
67
84
  }
68
85
  _log(event) {
86
+ this.#captureLog(event);
69
87
  switch(event.type){
70
88
  case 'unstable_server_log':
71
89
  var _event_data;
@@ -97,57 +115,11 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
97
115
  {
98
116
  if (this.shouldFilterClientLog(event)) {
99
117
  return;
100
- }
101
- const { level } = event;
102
- if (!level) {
118
+ } else if (event.level != null) {
119
+ return this.#onClientLog(event);
120
+ } else {
103
121
  break;
104
122
  }
105
- if (level === 'warn' || level === 'error') {
106
- let hasStack = false;
107
- const parsed = event.data.map((msg)=>{
108
- // Quick check to see if an unsymbolicated stack is being logged.
109
- if (msg.includes('.bundle//&platform=')) {
110
- const stack = (0, _serverLogLikeMetro.parseErrorStringToObject)(msg);
111
- if (stack) {
112
- hasStack = true;
113
- }
114
- return stack;
115
- }
116
- return msg;
117
- });
118
- if (hasStack) {
119
- (async ()=>{
120
- const symbolicating = parsed.map((p)=>{
121
- if (typeof p === 'string') return p;
122
- return (0, _serverLogLikeMetro.maybeSymbolicateAndFormatJSErrorStackLogAsync)(this.projectRoot, level, p);
123
- });
124
- let usefulStackCount = 0;
125
- const fallbackIndices = [];
126
- const symbolicated = (await Promise.allSettled(symbolicating)).map((s, index)=>{
127
- if (s.status === 'rejected') {
128
- debug('Error formatting stack', parsed[index], s.reason);
129
- return parsed[index];
130
- } else if (typeof s.value === 'string') {
131
- return s.value;
132
- } else {
133
- if (!s.value.isFallback) {
134
- usefulStackCount++;
135
- } else {
136
- fallbackIndices.push(index);
137
- }
138
- return s.value.stack;
139
- }
140
- });
141
- // Using EXPO_DEBUG we can print all stack
142
- const filtered = usefulStackCount && !_env.env.EXPO_DEBUG ? symbolicated.filter((_, index)=>!fallbackIndices.includes(index)) : symbolicated;
143
- (0, _serverLogLikeMetro.logLikeMetro)(this.terminal.log.bind(this.terminal), level, null, ...filtered);
144
- })();
145
- return;
146
- }
147
- }
148
- // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.
149
- (0, _serverLogLikeMetro.logLikeMetro)(this.terminal.log.bind(this.terminal), level, null, ...event.data);
150
- return;
151
123
  }
152
124
  }
153
125
  return super._log(event);
@@ -165,38 +137,46 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
165
137
  const env = getEnvironmentForBuildDetails(progress.bundleDetails);
166
138
  const platform = env || getPlatformTagForBuildDetails(progress.bundleDetails);
167
139
  const inProgress = phase === 'in_progress';
168
- let localPath;
169
- if (typeof ((_progress_bundleDetails = progress.bundleDetails) == null ? void 0 : (_progress_bundleDetails_customTransformOptions = _progress_bundleDetails.customTransformOptions) == null ? void 0 : _progress_bundleDetails_customTransformOptions.dom) === 'string' && progress.bundleDetails.customTransformOptions.dom.includes(_path().default.sep)) {
170
- // Because we use a generated entry file for DOM components, we need to adjust the logging path so it
171
- // shows a unique path for each component.
172
- // Here, we take the relative import path and remove all the starting slashes.
173
- localPath = progress.bundleDetails.customTransformOptions.dom.replace(/^(\.?\.[\\/])+/, '');
174
- } else {
175
- const inputFile = progress.bundleDetails.entryFile;
176
- localPath = _path().default.isAbsolute(inputFile) ? _path().default.relative(this.projectRoot, inputFile) : inputFile;
177
- }
140
+ const localPath = typeof ((_progress_bundleDetails = progress.bundleDetails) == null ? void 0 : (_progress_bundleDetails_customTransformOptions = _progress_bundleDetails.customTransformOptions) == null ? void 0 : _progress_bundleDetails_customTransformOptions.dom) === 'string' && progress.bundleDetails.customTransformOptions.dom.includes(_path().default.sep) ? progress.bundleDetails.customTransformOptions.dom.replace(/^(\.?\.[\\/])+/, '') : this.#normalizePath(progress.bundleDetails.entryFile);
178
141
  if (!inProgress) {
179
142
  const status = phase === 'done' ? `Bundled ` : `Bundling failed `;
180
143
  const color = phase === 'done' ? _chalk().default.green : _chalk().default.red;
181
144
  const startTime = this._bundleTimers.get(progress.bundleDetails.buildID);
182
145
  let time = '';
146
+ let ms = null;
183
147
  if (startTime != null) {
184
148
  const elapsed = this._getElapsedTime(startTime);
185
149
  const micro = Number(elapsed) / 1000;
186
- const converted = Number(elapsed) / 1e6;
150
+ ms = Number(elapsed) / 1e6;
187
151
  // If the milliseconds are < 0.5 then it will display as 0, so we display in microseconds.
188
- if (converted <= 0.5) {
152
+ if (ms <= 0.5) {
189
153
  const tenthFractionOfMicro = (micro * 10 / 1000).toFixed(0);
190
154
  // Format as microseconds to nearest tenth
191
155
  time = _chalk().default.cyan.bold(`0.${tenthFractionOfMicro}ms`);
192
156
  } else {
193
- time = _chalk().default.dim(converted.toFixed(0) + 'ms');
157
+ time = _chalk().default.dim(ms.toFixed(0) + 'ms');
194
158
  }
195
159
  }
160
+ if (phase === 'done') {
161
+ event('bundling:done', {
162
+ id: progress.bundleDetails.buildID ?? null,
163
+ total: progress.totalFileCount,
164
+ ms
165
+ });
166
+ }
196
167
  // iOS Bundled 150ms
197
168
  const plural = progress.totalFileCount === 1 ? '' : 's';
198
169
  return color(platform + status) + time + _chalk().default.reset.dim(` ${localPath} (${progress.totalFileCount} module${plural})`);
199
170
  }
171
+ event('bundling:progress', {
172
+ id: progress.bundleDetails.buildID ?? null,
173
+ progress: progress.ratio,
174
+ total: progress.totalFileCount,
175
+ current: progress.transformedFileCount
176
+ });
177
+ if ((0, _events.shouldReduceLogs)()) {
178
+ return '';
179
+ }
200
180
  const filledBar = Math.floor(progress.ratio * MAX_PROGRESS_BAR_CHAR_WIDTH);
201
181
  const _progress = inProgress ? _chalk().default.green.bgGreen(DARK_BLOCK_CHAR.repeat(filledBar)) + _chalk().default.bgWhite.white(LIGHT_BLOCK_CHAR.repeat(MAX_PROGRESS_BAR_CHAR_WIDTH - filledBar)) + _chalk().default.bold(` ${(100 * progress.ratio).toFixed(1).padStart(4)}% `) + _chalk().default.dim(`(${progress.transformedFileCount.toString().padStart(progress.totalFileCount.toString().length)}/${progress.totalFileCount})`) : '';
202
182
  return platform + _chalk().default.reset.dim(`${_path().default.dirname(localPath)}${_path().default.sep}`) + _chalk().default.bold(_path().default.basename(localPath)) + ' ' + _progress;
@@ -225,25 +205,145 @@ class MetroTerminalReporter extends _TerminalReporter.TerminalReporter {
225
205
  ].join('\n')));
226
206
  }
227
207
  }
208
+ /**
209
+ * Workaround to link build ids to bundling errors.
210
+ * This works because `_logBundleBuildFailed` is called before `_logBundlingError` in synchronous manner.
211
+ * https://github.com/facebook/metro/blob/main/packages/metro/src/Server.js#L939-L945
212
+ */ _logBundleBuildFailed(buildID) {
213
+ this.#lastFailedBuildID = buildID;
214
+ super._logBundleBuildFailed(buildID);
215
+ }
228
216
  _logBundlingError(error) {
229
- const moduleResolutionError = formatUsingNodeStandardLibraryError(this.projectRoot, error);
217
+ const importStack = (0, _metroErrorInterface.nearestImportStack)(error);
218
+ const moduleResolutionError = formatUsingNodeStandardLibraryError(this.serverRoot, error);
230
219
  if (moduleResolutionError) {
231
- let message = maybeAppendCodeFrame(moduleResolutionError, error.message);
232
- message += '\n\n' + (0, _metroErrorInterface.nearestImportStack)(error);
233
- return this.terminal.log(message);
220
+ const message = maybeAppendCodeFrame(moduleResolutionError, error.message);
221
+ event('bundling:failed', {
222
+ id: this.#lastFailedBuildID ?? null,
223
+ message: (0, _ansi.stripAnsi)(message) ?? null,
224
+ importStack: importStack ?? null,
225
+ filename: error.filename ?? null,
226
+ targetModuleName: this.#normalizePath(error.targetModuleName),
227
+ originModulePath: this.#normalizePath(error.originModulePath)
228
+ });
229
+ return this.terminal.log(importStack ? `${message}\n\n${importStack}` : message);
230
+ } else {
231
+ event('bundling:failed', {
232
+ id: this.#lastFailedBuildID ?? null,
233
+ message: (0, _ansi.stripAnsi)(error.message) ?? null,
234
+ importStack: importStack ?? null,
235
+ filename: error.filename ?? null,
236
+ targetModuleName: error.targetModuleName ?? null,
237
+ originModulePath: error.originModulePath ?? null
238
+ });
239
+ (0, _metroErrorInterface.attachImportStackToRootMessage)(error, importStack);
240
+ // NOTE(@kitten): Metro drops the stack forcefully when it finds a `SyntaxError`. However,
241
+ // this is really unhelpful, since it prevents debugging Babel plugins or reporting bugs
242
+ // in Babel plugins or a transformer entirely
243
+ if (error.snippet == null && error.stack != null && error instanceof SyntaxError) {
244
+ error.message = error.stack;
245
+ delete error.stack;
246
+ }
247
+ return super._logBundlingError(error);
234
248
  }
235
- (0, _metroErrorInterface.attachImportStackToRootMessage)(error);
236
- // NOTE(@kitten): Metro drops the stack forcefully when it finds a `SyntaxError`. However,
237
- // this is really unhelpful, since it prevents debugging Babel plugins or reporting bugs
238
- // in Babel plugins or a transformer entirely
239
- if (error.snippet == null && error.stack != null && error instanceof SyntaxError) {
240
- error.message = error.stack;
241
- delete error.stack;
249
+ }
250
+ #onClientLog(evt) {
251
+ const { level = 'log', data } = evt;
252
+ if (level === 'warn' || level === 'error') {
253
+ let hasStack = false;
254
+ const parsed = data.map((msg)=>{
255
+ // Quick check to see if an unsymbolicated stack is being logged.
256
+ if (typeof msg === 'string' && msg.includes('.bundle//&platform=')) {
257
+ const stack = (0, _serverLogLikeMetro.parseErrorStringToObject)(msg);
258
+ if (stack) {
259
+ hasStack = true;
260
+ }
261
+ return stack;
262
+ }
263
+ return msg;
264
+ });
265
+ if (hasStack) {
266
+ (async ()=>{
267
+ const symbolicating = parsed.map((p)=>{
268
+ if (typeof p === 'string') {
269
+ return p;
270
+ } else if (p && typeof p === 'object' && 'message' in p && typeof p.message === 'string') {
271
+ return (0, _serverLogLikeMetro.maybeSymbolicateAndFormatJSErrorStackLogAsync)(this.serverRoot, level, p);
272
+ } else {
273
+ return null;
274
+ }
275
+ });
276
+ let usefulStackCount = 0;
277
+ const fallbackIndices = [];
278
+ const symbolicated = (await Promise.allSettled(symbolicating)).map((s, index)=>{
279
+ if (s.status === 'rejected') {
280
+ debug('Error formatting stack', parsed[index], s.reason);
281
+ return parsed[index];
282
+ } else if (!s.value) {
283
+ return parsed[index];
284
+ } else if (typeof s.value === 'string') {
285
+ return s.value;
286
+ } else {
287
+ if (!s.value.isFallback) {
288
+ usefulStackCount++;
289
+ } else {
290
+ fallbackIndices.push(index);
291
+ }
292
+ return s.value.stack;
293
+ }
294
+ });
295
+ // Using EXPO_DEBUG we can print all stack
296
+ const filtered = usefulStackCount && !_env.env.EXPO_DEBUG ? symbolicated.filter((_, index)=>!fallbackIndices.includes(index)) : symbolicated;
297
+ event('client_log', {
298
+ level,
299
+ data: symbolicated
300
+ });
301
+ (0, _serverLogLikeMetro.logLikeMetro)(this.terminal.log.bind(this.terminal), level, null, ...filtered);
302
+ })();
303
+ return;
304
+ }
242
305
  }
243
- return super._logBundlingError(error);
306
+ event('client_log', {
307
+ level,
308
+ data
309
+ });
310
+ // Overwrite the Metro terminal logging so we can improve the warnings, symbolicate stacks, and inject extra info.
311
+ (0, _serverLogLikeMetro.logLikeMetro)(this.terminal.log.bind(this.terminal), level, null, ...data);
312
+ }
313
+ #captureLog(evt) {
314
+ switch(evt.type){
315
+ case 'bundle_build_started':
316
+ {
317
+ var _evt_bundleDetails_customTransformOptions, _evt_bundleDetails, _evt_bundleDetails_customTransformOptions1;
318
+ const entry = typeof ((_evt_bundleDetails = evt.bundleDetails) == null ? void 0 : (_evt_bundleDetails_customTransformOptions = _evt_bundleDetails.customTransformOptions) == null ? void 0 : _evt_bundleDetails_customTransformOptions.dom) === 'string' && evt.bundleDetails.customTransformOptions.dom.includes(_path().default.sep) ? evt.bundleDetails.customTransformOptions.dom.replace(/^(\.?\.[\\/])+/, '') : this.#normalizePath(evt.bundleDetails.entryFile);
319
+ return event('bundling:started', {
320
+ id: evt.buildID,
321
+ platform: evt.bundleDetails.platform ?? null,
322
+ environment: ((_evt_bundleDetails_customTransformOptions1 = evt.bundleDetails.customTransformOptions) == null ? void 0 : _evt_bundleDetails_customTransformOptions1.environment) ?? null,
323
+ entry
324
+ });
325
+ }
326
+ case 'unstable_server_log':
327
+ return event('server_log', {
328
+ level: evt.level ?? null,
329
+ data: evt.data ?? null
330
+ });
331
+ case 'client_log':
332
+ // Handled separately: see this.#onClientLog
333
+ return;
334
+ case 'hmr_client_error':
335
+ case 'cache_write_error':
336
+ case 'cache_read_error':
337
+ return event(evt.type, {
338
+ message: evt.error.message
339
+ });
340
+ }
341
+ }
342
+ #normalizePath(dest) {
343
+ return dest != null && _path().default.isAbsolute(dest) ? _path().default.relative(this.serverRoot, dest) : dest || null;
244
344
  }
245
345
  }
246
- function formatUsingNodeStandardLibraryError(projectRoot, error) {
346
+ function formatUsingNodeStandardLibraryError(serverRoot, error) {
247
347
  if (!error.message) {
248
348
  return null;
249
349
  }
@@ -251,7 +351,7 @@ function formatUsingNodeStandardLibraryError(projectRoot, error) {
251
351
  if (!targetModuleName || !originModulePath) {
252
352
  return null;
253
353
  }
254
- const relativePath = _path().default.relative(projectRoot, originModulePath);
354
+ const relativePath = _path().default.relative(serverRoot, originModulePath);
255
355
  const DOCS_PAGE_URL = 'https://docs.expo.dev/workflow/using-libraries/#using-third-party-libraries';
256
356
  if (isNodeStdLibraryModule(targetModuleName)) {
257
357
  if (originModulePath.includes('node_modules')) {