@expo/cli 57.0.3 → 57.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/events/index.js +1 -1
  3. package/build/src/export/publicFolder.js +2 -8
  4. package/build/src/export/publicFolder.js.map +1 -1
  5. package/build/src/start/interface/interactiveActions.js +42 -5
  6. package/build/src/start/interface/interactiveActions.js.map +1 -1
  7. package/build/src/start/interface/startInterface.js +4 -4
  8. package/build/src/start/interface/startInterface.js.map +1 -1
  9. package/build/src/start/server/DevToolsPlugin.js +57 -22
  10. package/build/src/start/server/DevToolsPlugin.js.map +1 -1
  11. package/build/src/start/server/DevToolsPlugin.schema.js +5 -0
  12. package/build/src/start/server/DevToolsPlugin.schema.js.map +1 -1
  13. package/build/src/start/server/DevToolsPluginManager.js +17 -3
  14. package/build/src/start/server/DevToolsPluginManager.js.map +1 -1
  15. package/build/src/start/server/DevToolsPluginServerHelpers.js +83 -0
  16. package/build/src/start/server/DevToolsPluginServerHelpers.js.map +1 -0
  17. package/build/src/start/server/MCP.js +10 -3
  18. package/build/src/start/server/MCP.js.map +1 -1
  19. package/build/src/start/server/metro/MetroBundlerDevServer.js +2 -1
  20. package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
  21. package/build/src/start/server/metro/instantiateMetro.js +18 -1
  22. package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
  23. package/build/src/start/server/middleware/DevToolsPluginMiddleware.js +57 -6
  24. package/build/src/start/server/middleware/DevToolsPluginMiddleware.js.map +1 -1
  25. package/build/src/start/startAsync.js +3 -0
  26. package/build/src/start/startAsync.js.map +1 -1
  27. package/build/src/utils/dir.js +10 -0
  28. package/build/src/utils/dir.js.map +1 -1
  29. package/build/src/utils/telemetry/Telemetry.js +5 -0
  30. package/build/src/utils/telemetry/Telemetry.js.map +1 -1
  31. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  32. package/build/src/utils/telemetry/utils/agent.js +42 -0
  33. package/build/src/utils/telemetry/utils/agent.js.map +1 -0
  34. package/build/src/utils/telemetry/utils/context.js +1 -1
  35. package/package.json +18 -18
  36. package/add-module.js +0 -8
package/build/bin/cli CHANGED
@@ -139,7 +139,7 @@ const args = (0, _arg().default)({
139
139
  });
140
140
  if (args['--version']) {
141
141
  // Version is added in the build script.
142
- console.log("57.0.3");
142
+ console.log("57.0.5");
143
143
  process.exit(0);
144
144
  }
145
145
  if (args['--non-interactive']) {
@@ -76,7 +76,7 @@ function getInitMetadata() {
76
76
  return {
77
77
  format: 'v0-jsonl',
78
78
  // Version is added in the build script.
79
- version: "57.0.3" ?? 'UNVERSIONED'
79
+ version: "57.0.5" ?? 'UNVERSIONED'
80
80
  };
81
81
  }
82
82
  function getWellKnownTemporaryLogFile(projectRoot, command) {
@@ -42,15 +42,9 @@ function _interop_require_default(obj) {
42
42
  };
43
43
  }
44
44
  const debug = require('debug')('expo:public-folder');
45
- const maybeRealpath = (target)=>{
46
- try {
47
- return _fs().default.realpathSync(target);
48
- } catch {
49
- return target;
50
- }
51
- };
52
45
  function getPublicFolderPath(projectRoot) {
53
- const publicPath = maybeRealpath(_path().default.resolve(projectRoot, _env.env.EXPO_PUBLIC_FOLDER));
46
+ const unresolvedPublicPath = _path().default.resolve(projectRoot, _env.env.EXPO_PUBLIC_FOLDER);
47
+ const publicPath = (0, _dir.maybeRealpathSync)(unresolvedPublicPath) ?? unresolvedPublicPath;
54
48
  if (!(0, _dir.isPathInside)(publicPath, projectRoot)) {
55
49
  throw new _errors.CommandError('EXPO_PUBLIC_FOLDER', `EXPO_PUBLIC_FOLDER ("${_env.env.EXPO_PUBLIC_FOLDER}") resolves to "${publicPath}", which is outside the project root "${projectRoot}". Set EXPO_PUBLIC_FOLDER to a path inside your project (e.g. "public").`);
56
50
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/export/publicFolder.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { copyAsync, isPathInside } from '../utils/dir';\nimport { env } from '../utils/env';\nimport { CommandError } from '../utils/errors';\n\nconst debug = require('debug')('expo:public-folder') as typeof console.log;\n\nconst maybeRealpath = (target: string) => {\n try {\n return fs.realpathSync(target);\n } catch {\n return target;\n }\n};\n\n/**\n * Resolve `EXPO_PUBLIC_FOLDER` against the project root and ensure the result\n * stays inside the project. An `EXPO_PUBLIC_FOLDER` value that escapes\n * (e.g. `../etc`, `/absolute/path`) almost always indicates a misconfigured\n * environment, and if honored would expose unrelated files via every consumer\n * that serves or copies the public folder.\n */\nexport function getPublicFolderPath(projectRoot: string): string {\n const publicPath = maybeRealpath(path.resolve(projectRoot, env.EXPO_PUBLIC_FOLDER));\n if (!isPathInside(publicPath, projectRoot)) {\n throw new CommandError(\n 'EXPO_PUBLIC_FOLDER',\n `EXPO_PUBLIC_FOLDER (\"${env.EXPO_PUBLIC_FOLDER}\") resolves to \"${publicPath}\", which is outside the project root \"${projectRoot}\". Set EXPO_PUBLIC_FOLDER to a path inside your project (e.g. \"public\").`\n );\n }\n return publicPath;\n}\n\n/** @returns the file system path for a user-defined file in the public folder. */\nexport function getUserDefinedFile(projectRoot: string, possiblePaths: string[]): string | null {\n const publicPath = getPublicFolderPath(projectRoot);\n\n for (const possiblePath of possiblePaths) {\n const fullPath = path.join(publicPath, possiblePath);\n if (fs.existsSync(fullPath)) {\n debug(`Found user-defined public file: ` + possiblePath);\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Copy the contents of the public folder into the output folder.\n * This enables users to add static files like `favicon.ico`.\n *\n * The contents of this folder are completely universal since they refer to\n * static network requests which fall outside the scope of React Native's magic\n * platform resolution patterns.\n */\nexport async function copyPublicFolderAsync(publicFolder: string, outputFolder: string) {\n if (fs.existsSync(publicFolder)) {\n await fs.promises.mkdir(outputFolder, { recursive: true });\n await copyAsync(publicFolder, outputFolder);\n }\n}\n"],"names":["copyPublicFolderAsync","getPublicFolderPath","getUserDefinedFile","debug","require","maybeRealpath","target","fs","realpathSync","projectRoot","publicPath","path","resolve","env","EXPO_PUBLIC_FOLDER","isPathInside","CommandError","possiblePaths","possiblePath","fullPath","join","existsSync","publicFolder","outputFolder","promises","mkdir","recursive","copyAsync"],"mappings":";;;;;;;;;;;QA0DsBA;eAAAA;;QAlCNC;eAAAA;;QAYAC;eAAAA;;;;gEApCD;;;;;;;gEACE;;;;;;qBAEuB;qBACpB;wBACS;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AAE/B,MAAMC,gBAAgB,CAACC;IACrB,IAAI;QACF,OAAOC,aAAE,CAACC,YAAY,CAACF;IACzB,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AASO,SAASL,oBAAoBQ,WAAmB;IACrD,MAAMC,aAAaL,cAAcM,eAAI,CAACC,OAAO,CAACH,aAAaI,QAAG,CAACC,kBAAkB;IACjF,IAAI,CAACC,IAAAA,iBAAY,EAACL,YAAYD,cAAc;QAC1C,MAAM,IAAIO,oBAAY,CACpB,sBACA,CAAC,qBAAqB,EAAEH,QAAG,CAACC,kBAAkB,CAAC,gBAAgB,EAAEJ,WAAW,sCAAsC,EAAED,YAAY,wEAAwE,CAAC;IAE7M;IACA,OAAOC;AACT;AAGO,SAASR,mBAAmBO,WAAmB,EAAEQ,aAAuB;IAC7E,MAAMP,aAAaT,oBAAoBQ;IAEvC,KAAK,MAAMS,gBAAgBD,cAAe;QACxC,MAAME,WAAWR,eAAI,CAACS,IAAI,CAACV,YAAYQ;QACvC,IAAIX,aAAE,CAACc,UAAU,CAACF,WAAW;YAC3BhB,MAAM,CAAC,gCAAgC,CAAC,GAAGe;YAC3C,OAAOC;QACT;IACF;IAEA,OAAO;AACT;AAUO,eAAenB,sBAAsBsB,YAAoB,EAAEC,YAAoB;IACpF,IAAIhB,aAAE,CAACc,UAAU,CAACC,eAAe;QAC/B,MAAMf,aAAE,CAACiB,QAAQ,CAACC,KAAK,CAACF,cAAc;YAAEG,WAAW;QAAK;QACxD,MAAMC,IAAAA,cAAS,EAACL,cAAcC;IAChC;AACF"}
1
+ {"version":3,"sources":["../../../src/export/publicFolder.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { copyAsync, isPathInside, maybeRealpathSync } from '../utils/dir';\nimport { env } from '../utils/env';\nimport { CommandError } from '../utils/errors';\n\nconst debug = require('debug')('expo:public-folder') as typeof console.log;\n\n/**\n * Resolve `EXPO_PUBLIC_FOLDER` against the project root and ensure the result\n * stays inside the project. An `EXPO_PUBLIC_FOLDER` value that escapes\n * (e.g. `../etc`, `/absolute/path`) almost always indicates a misconfigured\n * environment, and if honored would expose unrelated files via every consumer\n * that serves or copies the public folder.\n */\nexport function getPublicFolderPath(projectRoot: string): string {\n const unresolvedPublicPath = path.resolve(projectRoot, env.EXPO_PUBLIC_FOLDER);\n const publicPath = maybeRealpathSync(unresolvedPublicPath) ?? unresolvedPublicPath;\n if (!isPathInside(publicPath, projectRoot)) {\n throw new CommandError(\n 'EXPO_PUBLIC_FOLDER',\n `EXPO_PUBLIC_FOLDER (\"${env.EXPO_PUBLIC_FOLDER}\") resolves to \"${publicPath}\", which is outside the project root \"${projectRoot}\". Set EXPO_PUBLIC_FOLDER to a path inside your project (e.g. \"public\").`\n );\n }\n return publicPath;\n}\n\n/** @returns the file system path for a user-defined file in the public folder. */\nexport function getUserDefinedFile(projectRoot: string, possiblePaths: string[]): string | null {\n const publicPath = getPublicFolderPath(projectRoot);\n\n for (const possiblePath of possiblePaths) {\n const fullPath = path.join(publicPath, possiblePath);\n if (fs.existsSync(fullPath)) {\n debug(`Found user-defined public file: ` + possiblePath);\n return fullPath;\n }\n }\n\n return null;\n}\n\n/**\n * Copy the contents of the public folder into the output folder.\n * This enables users to add static files like `favicon.ico`.\n *\n * The contents of this folder are completely universal since they refer to\n * static network requests which fall outside the scope of React Native's magic\n * platform resolution patterns.\n */\nexport async function copyPublicFolderAsync(publicFolder: string, outputFolder: string) {\n if (fs.existsSync(publicFolder)) {\n await fs.promises.mkdir(outputFolder, { recursive: true });\n await copyAsync(publicFolder, outputFolder);\n }\n}\n"],"names":["copyPublicFolderAsync","getPublicFolderPath","getUserDefinedFile","debug","require","projectRoot","unresolvedPublicPath","path","resolve","env","EXPO_PUBLIC_FOLDER","publicPath","maybeRealpathSync","isPathInside","CommandError","possiblePaths","possiblePath","fullPath","join","fs","existsSync","publicFolder","outputFolder","promises","mkdir","recursive","copyAsync"],"mappings":";;;;;;;;;;;QAmDsBA;eAAAA;;QAnCNC;eAAAA;;QAaAC;eAAAA;;;;gEA7BD;;;;;;;gEACE;;;;;;qBAE0C;qBACvC;wBACS;;;;;;AAE7B,MAAMC,QAAQC,QAAQ,SAAS;AASxB,SAASH,oBAAoBI,WAAmB;IACrD,MAAMC,uBAAuBC,eAAI,CAACC,OAAO,CAACH,aAAaI,QAAG,CAACC,kBAAkB;IAC7E,MAAMC,aAAaC,IAAAA,sBAAiB,EAACN,yBAAyBA;IAC9D,IAAI,CAACO,IAAAA,iBAAY,EAACF,YAAYN,cAAc;QAC1C,MAAM,IAAIS,oBAAY,CACpB,sBACA,CAAC,qBAAqB,EAAEL,QAAG,CAACC,kBAAkB,CAAC,gBAAgB,EAAEC,WAAW,sCAAsC,EAAEN,YAAY,wEAAwE,CAAC;IAE7M;IACA,OAAOM;AACT;AAGO,SAAST,mBAAmBG,WAAmB,EAAEU,aAAuB;IAC7E,MAAMJ,aAAaV,oBAAoBI;IAEvC,KAAK,MAAMW,gBAAgBD,cAAe;QACxC,MAAME,WAAWV,eAAI,CAACW,IAAI,CAACP,YAAYK;QACvC,IAAIG,aAAE,CAACC,UAAU,CAACH,WAAW;YAC3Bd,MAAM,CAAC,gCAAgC,CAAC,GAAGa;YAC3C,OAAOC;QACT;IACF;IAEA,OAAO;AACT;AAUO,eAAejB,sBAAsBqB,YAAoB,EAAEC,YAAoB;IACpF,IAAIH,aAAE,CAACC,UAAU,CAACC,eAAe;QAC/B,MAAMF,aAAE,CAACI,QAAQ,CAACC,KAAK,CAACF,cAAc;YAAEG,WAAW;QAAK;QACxD,MAAMC,IAAAA,cAAS,EAACL,cAAcC;IAChC;AACF"}
@@ -2,10 +2,21 @@
2
2
  Object.defineProperty(exports, "__esModule", {
3
3
  value: true
4
4
  });
5
- Object.defineProperty(exports, "DevServerManagerActions", {
6
- enumerable: true,
7
- get: function() {
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 DevServerManagerActions () {
8
13
  return DevServerManagerActions;
14
+ },
15
+ get getDevToolsPluginCliBannerItems () {
16
+ return getDevToolsPluginCliBannerItems;
17
+ },
18
+ get printDevToolsPluginCliBannersAsync () {
19
+ return printDevToolsPluginCliBannersAsync;
9
20
  }
10
21
  });
11
22
  function _chalk() {
@@ -71,12 +82,36 @@ function _interop_require_wildcard(obj, nodeInterop) {
71
82
  return newObj;
72
83
  }
73
84
  const debug = require('debug')('expo:start:interface:interactiveActions');
85
+ function getDevToolsPluginCliBannerItems(plugins, defaultServerUrl) {
86
+ return plugins.filter((plugin)=>plugin.cliBanner && plugin.webpageEndpoint != null).map((plugin)=>({
87
+ title: plugin.bannerTitle,
88
+ url: new URL(plugin.webpageEndpoint, defaultServerUrl).toString()
89
+ }));
90
+ }
91
+ async function printDevToolsPluginCliBannersAsync(devServerManager) {
92
+ if (!devServerManager.getNativeDevServerPort()) {
93
+ return 0;
94
+ }
95
+ try {
96
+ const plugins = await devServerManager.devtoolsPluginManager.queryPluginsAsync();
97
+ const bannerItems = getDevToolsPluginCliBannerItems(plugins, devServerManager.getDefaultDevServer().getUrlCreator().constructUrl({
98
+ scheme: 'http'
99
+ }));
100
+ for (const { title, url } of bannerItems){
101
+ _log.log((0, _commandsTable.printItem)((0, _chalk().default)`${title}: {underline ${url}}`));
102
+ }
103
+ return bannerItems.length;
104
+ } catch (error) {
105
+ debug(`Failed to print DevTools plugin CLI banners: ${error.toString()}`);
106
+ return 0;
107
+ }
108
+ }
74
109
  class DevServerManagerActions {
75
110
  constructor(devServerManager, options){
76
111
  this.devServerManager = devServerManager;
77
112
  this.options = options;
78
113
  }
79
- printDevServerInfo(options) {
114
+ async printDevServerInfoAsync(options) {
80
115
  var _this_options_platforms, _options_dependencyCheckRef;
81
116
  // Keep track of approximately how much space we have to print our usage guide
82
117
  let rows = process.stdout.rows || Infinity;
@@ -123,8 +158,9 @@ class DevServerManagerActions {
123
158
  } else {
124
159
  const serverUrl = devServer.getDevServerUrl();
125
160
  _log.log((0, _commandsTable.printItem)((0, _chalk().default)`Metro: {underline ${serverUrl}}`));
161
+ rows--;
126
162
  _log.log((0, _commandsTable.printItem)(`Linking is disabled because the client scheme cannot be resolved.`));
127
- rows -= 2;
163
+ rows--;
128
164
  }
129
165
  }
130
166
  }
@@ -138,6 +174,7 @@ class DevServerManagerActions {
138
174
  rows--;
139
175
  }
140
176
  }
177
+ rows -= await printDevToolsPluginCliBannersAsync(this.devServerManager);
141
178
  const dependencyCheckLines = (0, _checkDependenciesOnStart.getDependencyCheckMessage)((_options_dependencyCheckRef = options.dependencyCheckRef) == null ? void 0 : _options_dependencyCheckRef.result);
142
179
  rows -= dependencyCheckLines.length;
143
180
  (0, _commandsTable.printUsage)(options, {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/interface/interactiveActions.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport type { StartOptions } from './commandsTable';\nimport { BLT, printHelp, printItem, printUsage } from './commandsTable';\nimport { createDevToolsMenuItems } from './createDevToolsMenuItems';\nimport * as Log from '../../log';\nimport { env } from '../../utils/env';\nimport { learnMore } from '../../utils/link';\nimport type { ExpoChoice } from '../../utils/prompts';\nimport { selectAsync } from '../../utils/prompts';\nimport { printQRCode } from '../../utils/qr';\nimport { getDependencyCheckMessage } from '../checkDependenciesOnStart';\nimport type { 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<\n StartOptions,\n 'devClient' | 'isWebSocketsEnabled' | 'platforms' | 'dependencyCheckRef'\n >\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 const dependencyCheckLines = getDependencyCheckMessage(options.dependencyCheckRef?.result);\n rows -= dependencyCheckLines.length;\n\n printUsage(options, { verbose: false, rows });\n printHelp();\n Log.log();\n\n for (const line of dependencyCheckLines) {\n Log.log(line);\n }\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","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","dependencyCheckLines","getDependencyCheckMessage","dependencyCheckRef","result","length","printUsage","verbose","printHelp","line","openJsInspectorAsync","metroServerOrigin","getJsInspectorBaseUrl","apps","queryAllInspectorAppsAsync","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 type { StartOptions } from './commandsTable';\nimport { BLT, printHelp, printItem, printUsage } from './commandsTable';\nimport { createDevToolsMenuItems } from './createDevToolsMenuItems';\nimport * as Log from '../../log';\nimport { env } from '../../utils/env';\nimport { learnMore } from '../../utils/link';\nimport type { ExpoChoice } from '../../utils/prompts';\nimport { selectAsync } from '../../utils/prompts';\nimport { printQRCode } from '../../utils/qr';\nimport { getDependencyCheckMessage } from '../checkDependenciesOnStart';\nimport type { DevServerManager } from '../server/DevServerManager';\nimport type { DevToolsPlugin } from '../server/DevToolsPlugin';\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\nexport function getDevToolsPluginCliBannerItems(\n plugins: DevToolsPlugin[],\n defaultServerUrl: string\n): { title: string; url: string }[] {\n return plugins\n .filter((plugin) => plugin.cliBanner && plugin.webpageEndpoint != null)\n .map((plugin) => ({\n title: plugin.bannerTitle,\n url: new URL(plugin.webpageEndpoint!, defaultServerUrl).toString(),\n }));\n}\n\nexport async function printDevToolsPluginCliBannersAsync(\n devServerManager: DevServerManager\n): Promise<number> {\n if (!devServerManager.getNativeDevServerPort()) {\n return 0;\n }\n\n try {\n const plugins = await devServerManager.devtoolsPluginManager.queryPluginsAsync();\n const bannerItems = getDevToolsPluginCliBannerItems(\n plugins,\n devServerManager.getDefaultDevServer().getUrlCreator().constructUrl({ scheme: 'http' })\n );\n\n for (const { title, url } of bannerItems) {\n Log.log(printItem(chalk`${title}: {underline ${url}}`));\n }\n\n return bannerItems.length;\n } catch (error: any) {\n debug(`Failed to print DevTools plugin CLI banners: ${error.toString()}`);\n return 0;\n }\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 async printDevServerInfoAsync(\n options: Pick<\n StartOptions,\n 'devClient' | 'isWebSocketsEnabled' | 'platforms' | 'dependencyCheckRef'\n >\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 rows--;\n Log.log(printItem(`Linking is disabled because the client scheme cannot be resolved.`));\n rows--;\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 rows -= await printDevToolsPluginCliBannersAsync(this.devServerManager);\n\n const dependencyCheckLines = getDependencyCheckMessage(options.dependencyCheckRef?.result);\n rows -= dependencyCheckLines.length;\n\n printUsage(options, { verbose: false, rows });\n printHelp();\n Log.log();\n\n for (const line of dependencyCheckLines) {\n Log.log(line);\n }\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","getDevToolsPluginCliBannerItems","printDevToolsPluginCliBannersAsync","debug","require","plugins","defaultServerUrl","filter","plugin","cliBanner","webpageEndpoint","map","title","bannerTitle","url","URL","toString","devServerManager","getNativeDevServerPort","devtoolsPluginManager","queryPluginsAsync","bannerItems","getDefaultDevServer","getUrlCreator","constructUrl","scheme","Log","log","printItem","chalk","length","error","options","printDevServerInfoAsync","rows","process","stdout","Infinity","devServer","nativeRuntimeUrl","getNativeRuntimeUrl","interstitialPageUrl","getRedirectUrl","env","__EXPO_E2E_TEST","console","info","JSON","stringify","getDevServerUrl","EXPO_NO_QR_CODE","qr","printQRCode","lines","print","qrMessage","devClient","learnMore","dim","code","serverUrl","platforms","includes","webDevServer","getWebDevServer","webUrl","hostType","dependencyCheckLines","getDependencyCheckMessage","dependencyCheckRef","result","printUsage","verbose","printHelp","line","openJsInspectorAsync","metroServerOrigin","getJsInspectorBaseUrl","apps","queryAllInspectorAppsAsync","warn","app","promptInspectorAppAsync","openJsInspector","exception","reloadApp","BLT","broadcastMessage","openMoreToolsAsync","defaultMenuItems","value","menuItems","createDevToolsMenuItems","selectAsync","menuItem","find","item","action","name","toggleDevMenu"],"mappings":";;;;;;;;;;;QAgEaA;eAAAA;;QAtCGC;eAAAA;;QAYMC;eAAAA;;;;gEAtCJ;;;;;;+BAGoC;yCACd;6DACnB;qBACD;sBACM;yBAEE;oBACA;0CACc;6BAOnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEP,MAAMC,QAAQC,QAAQ,SAAS;AAMxB,SAASH,gCACdI,OAAyB,EACzBC,gBAAwB;IAExB,OAAOD,QACJE,MAAM,CAAC,CAACC,SAAWA,OAAOC,SAAS,IAAID,OAAOE,eAAe,IAAI,MACjEC,GAAG,CAAC,CAACH,SAAY,CAAA;YAChBI,OAAOJ,OAAOK,WAAW;YACzBC,KAAK,IAAIC,IAAIP,OAAOE,eAAe,EAAGJ,kBAAkBU,QAAQ;QAClE,CAAA;AACJ;AAEO,eAAed,mCACpBe,gBAAkC;IAElC,IAAI,CAACA,iBAAiBC,sBAAsB,IAAI;QAC9C,OAAO;IACT;IAEA,IAAI;QACF,MAAMb,UAAU,MAAMY,iBAAiBE,qBAAqB,CAACC,iBAAiB;QAC9E,MAAMC,cAAcpB,gCAClBI,SACAY,iBAAiBK,mBAAmB,GAAGC,aAAa,GAAGC,YAAY,CAAC;YAAEC,QAAQ;QAAO;QAGvF,KAAK,MAAM,EAAEb,KAAK,EAAEE,GAAG,EAAE,IAAIO,YAAa;YACxCK,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAACC,IAAAA,gBAAK,CAAA,CAAC,EAAEjB,MAAM,aAAa,EAAEE,IAAI,CAAC,CAAC;QACvD;QAEA,OAAOO,YAAYS,MAAM;IAC3B,EAAE,OAAOC,OAAY;QACnB5B,MAAM,CAAC,6CAA6C,EAAE4B,MAAMf,QAAQ,IAAI;QACxE,OAAO;IACT;AACF;AAGO,MAAMhB;IACX,YACE,AAAQiB,gBAAkC,EAC1C,AAAQe,OAAsD,CAC9D;aAFQf,mBAAAA;aACAe,UAAAA;IACP;IAEH,MAAMC,wBACJD,OAGC,EACD;YA6DI,yBAWmDA;QAvEvD,8EAA8E;QAC9E,IAAIE,OAAOC,QAAQC,MAAM,CAACF,IAAI,IAAIG;QAElC,kDAAkD;QAClD,IAAI,IAAI,CAACpB,gBAAgB,CAACC,sBAAsB,IAAI;YAClD,MAAMoB,YAAY,IAAI,CAACrB,gBAAgB,CAACK,mBAAmB;YAC3D,IAAI;gBACF,MAAMiB,mBAAmBD,UAAUE,mBAAmB;gBACtD,MAAMC,sBAAsBH,UAAUI,cAAc;gBAEpD,oCAAoC;gBACpC,IAAIC,QAAG,CAACC,eAAe,EAAE;oBACvBC,QAAQC,IAAI,CACV,CAAC,yBAAyB,EAAEC,KAAKC,SAAS,CAAC;wBAAElC,KAAKwB,UAAUW,eAAe;oBAAG,IAAI;oBAEpFf;gBACF;gBAEA,IAAI,CAACS,QAAG,CAACO,eAAe,EAAE;oBACxB,MAAMC,KAAKC,IAAAA,eAAW,EAACX,uBAAuBF;oBAC9CL,QAAQiB,GAAGE,KAAK;oBAChBF,GAAGG,KAAK;oBAER,IAAIC,YAAY;oBAChB,IAAI,CAACvB,QAAQwB,SAAS,EAAE;wBACtBD,YAAY,CAAC,kCAAkC,EAAE1B,IAAAA,gBAAK,CAAA,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;oBAC3E,OAAO;wBACL0B,YAAY1B,IAAAA,gBAAK,CAAA,CAAC,6DAA6D,CAAC;wBAChF0B,aAAa,CAAC,EAAE,EAAEE,IAAAA,eAAS,EAAC,0BAA0B,CAAC,CAAC;oBAC1D;oBACAvB;oBACAR,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAAC2B,WAAW;wBAAEG,KAAK;oBAAK;gBAC3C;gBAEA,IAAIjB,qBAAqB;oBACvBP;oBACAR,KAAIC,GAAG,CACLC,IAAAA,wBAAS,EACPC,IAAAA,gBAAK,CAAA,CAAC,iDAAiD,EAAEY,oBAAoB,CAAC,CAAC;gBAGrF;gBAEAP;gBACAR,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAACC,IAAAA,gBAAK,CAAA,CAAC,kBAAkB,EAAEU,iBAAiB,CAAC,CAAC;YACjE,EAAE,OAAOR,OAAO;gBACdc,QAAQlB,GAAG,CAAC,OAAOI;gBACnB,8EAA8E;gBAC9E,IAAIA,MAAM4B,IAAI,KAAK,wBAAwB;oBACzC,MAAM5B;gBACR,OAAO;oBACL,MAAM6B,YAAYtB,UAAUW,eAAe;oBAC3CvB,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAACC,IAAAA,gBAAK,CAAA,CAAC,kBAAkB,EAAE+B,UAAU,CAAC,CAAC;oBACxD1B;oBACAR,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAAC,CAAC,iEAAiE,CAAC;oBACrFM;gBACF;YACF;QACF;QAEA,KAAI,0BAAA,IAAI,CAACF,OAAO,CAAC6B,SAAS,qBAAtB,wBAAwBC,QAAQ,CAAC,QAAQ;YAC3C,MAAMC,eAAe,IAAI,CAAC9C,gBAAgB,CAAC+C,eAAe;YAC1D,MAAMC,SAASF,gCAAAA,aAAcd,eAAe,CAAC;gBAAEiB,UAAU;YAAY;YACrE,IAAID,QAAQ;gBACVvC,KAAIC,GAAG,CAACC,IAAAA,wBAAS,EAACC,IAAAA,gBAAK,CAAA,CAAC,gBAAgB,EAAEoC,OAAO,CAAC,CAAC;gBACnD/B;YACF;QACF;QAEAA,QAAQ,MAAMhC,mCAAmC,IAAI,CAACe,gBAAgB;QAEtE,MAAMkD,uBAAuBC,IAAAA,mDAAyB,GAACpC,8BAAAA,QAAQqC,kBAAkB,qBAA1BrC,4BAA4BsC,MAAM;QACzFpC,QAAQiC,qBAAqBrC,MAAM;QAEnCyC,IAAAA,yBAAU,EAACvC,SAAS;YAAEwC,SAAS;YAAOtC;QAAK;QAC3CuC,IAAAA,wBAAS;QACT/C,KAAIC,GAAG;QAEP,KAAK,MAAM+C,QAAQP,qBAAsB;YACvCzC,KAAIC,GAAG,CAAC+C;QACV;IACF;IAEA,MAAMC,uBAAuB;QAC3B,IAAI;YACF,MAAMC,oBAAoB,IAAI,CAAC3D,gBAAgB,CAACK,mBAAmB,GAAGuD,qBAAqB;YAC3F,MAAMC,OAAO,MAAMC,IAAAA,uCAA0B,EAACH;YAC9C,IAAI,CAACE,KAAKhD,MAAM,EAAE;gBAChB,OAAOJ,KAAIsD,IAAI,CACbnD,IAAAA,gBAAK,CAAA,CAAC,gGAAgG,EAAE4B,IAAAA,eAAS,EAC/G,8CACA,CAAC;YAEP;YAEA,MAAMwB,MAAM,MAAMC,IAAAA,oCAAuB,EAACJ;YAC1C,IAAI,CAACG,KAAK;gBACR,OAAOvD,KAAIK,KAAK,CAACF,IAAAA,gBAAK,CAAA,CAAC,4CAA4C,CAAC;YACtE;YAEA,IAAI,CAAE,MAAMsD,IAAAA,4BAAe,EAACP,mBAAmBK,MAAO;gBACpDvD,KAAIsD,IAAI,CACNnD,IAAAA,gBAAK,CAAA,CAAC,qFAAqF,CAAC;YAEhG;QACF,EAAE,OAAOE,OAAY;YACnB,yBAAyB;YACzB,IAAIA,MAAM4B,IAAI,KAAK,WAAW;YAE9BjC,KAAIK,KAAK,CAAC;YACVL,KAAI0D,SAAS,CAACrD;QAChB;IACF;IAEAsD,YAAY;QACV3D,KAAIC,GAAG,CAAC,GAAG2D,kBAAG,CAAC,eAAe,CAAC;QAC/B,4CAA4C;QAC5C,IAAI,CAACrE,gBAAgB,CAACsE,gBAAgB,CAAC;IACzC;IAEA,MAAMC,qBAAqB;QACzB,2CAA2C;QAC3C,IAAI;YACF,MAAMC,mBAAuC;gBAC3C;oBAAE7E,OAAO;oBAAoB8E,OAAO;gBAAyB;gBAC7D;oBAAE9E,OAAO;oBAA8B8E,OAAO;gBAA2B;gBACzE;oBAAE9E,OAAO;oBAAyB8E,OAAO;gBAAgB;gBACzD;oBAAE9E,OAAO;oBAAc8E,OAAO;gBAAS;aAExC;YAED,MAAMpF,mBAAmB,IAAI,CAACW,gBAAgB,CAC3CK,mBAAmB,GACnBC,aAAa,GACbC,YAAY,CAAC;gBAAEC,QAAQ;YAAO;YAEjC,MAAMmD,oBAAoB,IAAI,CAAC3D,gBAAgB,CAACK,mBAAmB,GAAGuD,qBAAqB;YAC3F,MAAMxE,UAAU,MAAM,IAAI,CAACY,gBAAgB,CAACE,qBAAqB,CAACC,iBAAiB;YAEnF,MAAMuE,YAAY;mBACbF;mBACAG,IAAAA,gDAAuB,EAACvF,SAASC,kBAAkBsE;aACvD;YAED,MAAMc,QAAQ,MAAMG,IAAAA,oBAAW,EAAChE,IAAAA,gBAAK,CAAA,CAAC,6BAA6B,CAAC,EAAE8D;YACtE,MAAMG,WAAWH,UAAUI,IAAI,CAAC,CAACC,OAASA,KAAKN,KAAK,KAAKA;YACzD,IAAII,4BAAAA,SAAUG,MAAM,EAAE;gBACpBH,SAASG,MAAM;YACjB,OAAO,IAAIH,4BAAAA,SAAUJ,KAAK,EAAE;gBAC1B,IAAI,CAACzE,gBAAgB,CAACsE,gBAAgB,CAAC,kBAAkB;oBAAEW,MAAMJ,SAASJ,KAAK;gBAAC;YAClF;QACF,EAAE,OAAO3D,OAAY;YACnB5B,MAAM4B;QACN,aAAa;QACf,SAAU;YACR0C,IAAAA,wBAAS;QACX;IACF;IAEA0B,gBAAgB;QACdzE,KAAIC,GAAG,CAAC,GAAG2D,kBAAG,CAAC,kBAAkB,CAAC;QAClC,IAAI,CAACrE,gBAAgB,CAACsE,gBAAgB,CAAC;IACzC;AACF"}
@@ -103,7 +103,7 @@ async function startInterfaceAsync(devServerManager, options) {
103
103
  devClient: devServerManager.options.devClient,
104
104
  ...options
105
105
  };
106
- actions.printDevServerInfo(usageOptions);
106
+ await actions.printDevServerInfoAsync(usageOptions);
107
107
  const onPressAsync = async (key)=>{
108
108
  // Auxillary commands all escape.
109
109
  switch(key){
@@ -205,7 +205,7 @@ async function startInterfaceAsync(devServerManager, options) {
205
205
  _log.clear();
206
206
  if (await devServerManager.toggleRuntimeMode()) {
207
207
  usageOptions.devClient = devServerManager.options.devClient;
208
- actions.printDevServerInfo(usageOptions);
208
+ await actions.printDevServerInfoAsync(usageOptions);
209
209
  return;
210
210
  }
211
211
  break;
@@ -233,7 +233,7 @@ async function startInterfaceAsync(devServerManager, options) {
233
233
  debug('Starting up webpack dev server');
234
234
  await devServerManager.ensureWebDevServerRunningAsync();
235
235
  // When this is the first time webpack is started, reprint the connection info.
236
- actions.printDevServerInfo(usageOptions);
236
+ await actions.printDevServerInfoAsync(usageOptions);
237
237
  }
238
238
  _log.log(`${_commandsTable.BLT} Open in the web browser...`);
239
239
  try {
@@ -249,7 +249,7 @@ async function startInterfaceAsync(devServerManager, options) {
249
249
  }
250
250
  case 'c':
251
251
  _log.clear();
252
- actions.printDevServerInfo(usageOptions);
252
+ await actions.printDevServerInfoAsync(usageOptions);
253
253
  return;
254
254
  case 'j':
255
255
  return actions.openJsInspectorAsync();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/interface/startInterface.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { KeyPressHandler } from './KeyPressHandler';\nimport type { StartOptions } from './commandsTable';\nimport { BLT, printHelp, printUsage } from './commandsTable';\nimport { DevServerManagerActions } from './interactiveActions';\nimport * as Log from '../../log';\nimport { openInEditorAsync } from '../../utils/editor';\nimport { AbortCommandError } from '../../utils/errors';\nimport { getAllSpinners, ora } from '../../utils/ora';\nimport { getProgressBar, setProgressBar } from '../../utils/progress';\nimport { addInteractionListener, pauseInteractions } from '../../utils/prompts';\nimport { WebSupportProjectPrerequisite } from '../doctor/web/WebSupportProjectPrerequisite';\nimport type { DevServerManager } from '../server/DevServerManager';\n\nconst debug = require('debug')('expo:start:interface:startInterface') as typeof console.log;\n\nconst CTRL_C = '\\u0003';\nconst CTRL_D = '\\u0004';\nconst CTRL_L = '\\u000C';\n\nconst PLATFORM_SETTINGS: Record<\n string,\n { name: string; key: 'android' | 'ios'; launchTarget: 'emulator' | 'simulator' }\n> = {\n android: {\n name: 'Android',\n key: 'android',\n launchTarget: 'emulator',\n },\n ios: {\n name: 'iOS',\n key: 'ios',\n launchTarget: 'simulator',\n },\n};\n\nexport async function startInterfaceAsync(\n devServerManager: DevServerManager,\n options: Pick<StartOptions, 'devClient' | 'platforms' | 'mcpServer' | 'dependencyCheckRef'>\n) {\n // Spend one-tick waiting for the dependency check result\n if (options.dependencyCheckRef) {\n await Promise.race([options.dependencyCheckRef.promise, Promise.resolve(null)]);\n }\n\n const actions = new DevServerManagerActions(devServerManager, options);\n const isWebSocketsEnabled = devServerManager.getDefaultDevServer()?.isTargetingNative();\n const usageOptions = {\n isWebSocketsEnabled,\n devClient: devServerManager.options.devClient,\n ...options,\n };\n\n actions.printDevServerInfo(usageOptions);\n\n const onPressAsync = async (key: string) => {\n // Auxillary commands all escape.\n switch (key) {\n case CTRL_C:\n case CTRL_D: {\n // Prevent terminal UI from accepting commands while the process is closing.\n // Without this, fast typers will close the server then start typing their\n // next command and have a bunch of unrelated things pop up.\n pauseInteractions();\n\n const spinners = getAllSpinners();\n spinners.forEach((spinner) => {\n spinner.fail();\n });\n\n const currentProgress = getProgressBar();\n if (currentProgress) {\n currentProgress.terminate();\n setProgressBar(null);\n }\n const spinner = ora({ text: 'Stopping server', color: 'white' }).start();\n try {\n await devServerManager.stopAsync();\n if (options.mcpServer) {\n await options.mcpServer.closeAsync();\n }\n spinner.stopAndPersist({ text: 'Stopped server', symbol: `\\u203A` });\n // @ts-ignore: Argument of type '\"SIGINT\"' is not assignable to parameter of type '\"disconnect\"'.\n process.emit('SIGINT');\n\n // TODO: Is this the right place to do this?\n process.exit();\n } catch (error) {\n spinner.fail('Failed to stop server');\n throw error;\n }\n break;\n }\n case CTRL_L:\n return Log.clear();\n case '?':\n return printUsage(usageOptions, { verbose: true });\n }\n\n // Optionally enabled\n\n if (isWebSocketsEnabled) {\n switch (key) {\n case 'm':\n return actions.toggleDevMenu();\n case 'M':\n return actions.openMoreToolsAsync();\n }\n }\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n if (['i', 'a'].includes(key.toLowerCase())) {\n const platform = key.toLowerCase() === 'i' ? 'ios' : 'android';\n\n const shouldPrompt = ['I', 'A'].includes(key);\n if (shouldPrompt) {\n Log.clear();\n }\n\n const server = devServerManager.getDefaultDevServer();\n const settings = PLATFORM_SETTINGS[platform]!;\n\n Log.log(`${BLT} Opening on ${settings.name}...`);\n\n if (server.isTargetingNative() && !platforms.includes(settings.key)) {\n Log.warn(\n chalk`${settings.name} is disabled, enable it by adding {bold ${settings.key}} to the platforms array in your app.json or app.config.js`\n );\n } else {\n try {\n await server.openPlatformAsync(settings.launchTarget, { shouldPrompt });\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n }\n // Break out early.\n return;\n }\n\n switch (key) {\n case 's': {\n Log.clear();\n if (await devServerManager.toggleRuntimeMode()) {\n usageOptions.devClient = devServerManager.options.devClient;\n actions.printDevServerInfo(usageOptions);\n return;\n }\n break;\n }\n case 'w': {\n try {\n await devServerManager.ensureProjectPrerequisiteAsync(WebSupportProjectPrerequisite);\n if (!platforms.includes('web')) {\n platforms.push('web');\n options.platforms?.push('web');\n }\n } catch (e: any) {\n Log.warn(e.message);\n break;\n }\n\n const isDisabled = !platforms.includes('web');\n if (isDisabled) {\n debug('Web is disabled');\n // Use warnings from the web support setup.\n break;\n }\n\n // Ensure the Webpack dev server is running first\n if (!devServerManager.getWebDevServer()) {\n debug('Starting up webpack dev server');\n await devServerManager.ensureWebDevServerRunningAsync();\n // When this is the first time webpack is started, reprint the connection info.\n actions.printDevServerInfo(usageOptions);\n }\n\n Log.log(`${BLT} Open in the web browser...`);\n try {\n await devServerManager.getWebDevServer()?.openPlatformAsync('desktop');\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n break;\n }\n case 'c':\n Log.clear();\n actions.printDevServerInfo(usageOptions);\n return;\n case 'j':\n return actions.openJsInspectorAsync();\n case 'r':\n return actions.reloadApp();\n case 'o':\n Log.log(`${BLT} Opening the editor...`);\n return openInEditorAsync(devServerManager.projectRoot);\n }\n };\n\n const keyPressHandler = new KeyPressHandler(onPressAsync);\n\n const listener = keyPressHandler.createInteractionListener();\n\n addInteractionListener(listener);\n\n // Start observing...\n keyPressHandler.startInterceptingKeyStrokes();\n}\n"],"names":["startInterfaceAsync","debug","require","CTRL_C","CTRL_D","CTRL_L","PLATFORM_SETTINGS","android","name","key","launchTarget","ios","devServerManager","options","dependencyCheckRef","Promise","race","promise","resolve","actions","DevServerManagerActions","isWebSocketsEnabled","getDefaultDevServer","isTargetingNative","usageOptions","devClient","printDevServerInfo","onPressAsync","pauseInteractions","spinners","getAllSpinners","forEach","spinner","fail","currentProgress","getProgressBar","terminate","setProgressBar","ora","text","color","start","stopAsync","mcpServer","closeAsync","stopAndPersist","symbol","process","emit","exit","error","Log","clear","printUsage","verbose","toggleDevMenu","openMoreToolsAsync","platforms","includes","toLowerCase","platform","shouldPrompt","server","settings","log","BLT","warn","chalk","openPlatformAsync","printHelp","AbortCommandError","exception","toggleRuntimeMode","ensureProjectPrerequisiteAsync","WebSupportProjectPrerequisite","push","e","message","isDisabled","getWebDevServer","ensureWebDevServerRunningAsync","openJsInspectorAsync","reloadApp","openInEditorAsync","projectRoot","keyPressHandler","KeyPressHandler","listener","createInteractionListener","addInteractionListener","startInterceptingKeyStrokes"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/start/interface/startInterface.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { KeyPressHandler } from './KeyPressHandler';\nimport type { StartOptions } from './commandsTable';\nimport { BLT, printHelp, printUsage } from './commandsTable';\nimport { DevServerManagerActions } from './interactiveActions';\nimport * as Log from '../../log';\nimport { openInEditorAsync } from '../../utils/editor';\nimport { AbortCommandError } from '../../utils/errors';\nimport { getAllSpinners, ora } from '../../utils/ora';\nimport { getProgressBar, setProgressBar } from '../../utils/progress';\nimport { addInteractionListener, pauseInteractions } from '../../utils/prompts';\nimport { WebSupportProjectPrerequisite } from '../doctor/web/WebSupportProjectPrerequisite';\nimport type { DevServerManager } from '../server/DevServerManager';\n\nconst debug = require('debug')('expo:start:interface:startInterface') as typeof console.log;\n\nconst CTRL_C = '\\u0003';\nconst CTRL_D = '\\u0004';\nconst CTRL_L = '\\u000C';\n\nconst PLATFORM_SETTINGS: Record<\n string,\n { name: string; key: 'android' | 'ios'; launchTarget: 'emulator' | 'simulator' }\n> = {\n android: {\n name: 'Android',\n key: 'android',\n launchTarget: 'emulator',\n },\n ios: {\n name: 'iOS',\n key: 'ios',\n launchTarget: 'simulator',\n },\n};\n\nexport async function startInterfaceAsync(\n devServerManager: DevServerManager,\n options: Pick<StartOptions, 'devClient' | 'platforms' | 'mcpServer' | 'dependencyCheckRef'>\n) {\n // Spend one-tick waiting for the dependency check result\n if (options.dependencyCheckRef) {\n await Promise.race([options.dependencyCheckRef.promise, Promise.resolve(null)]);\n }\n\n const actions = new DevServerManagerActions(devServerManager, options);\n const isWebSocketsEnabled = devServerManager.getDefaultDevServer()?.isTargetingNative();\n const usageOptions = {\n isWebSocketsEnabled,\n devClient: devServerManager.options.devClient,\n ...options,\n };\n\n await actions.printDevServerInfoAsync(usageOptions);\n\n const onPressAsync = async (key: string) => {\n // Auxillary commands all escape.\n switch (key) {\n case CTRL_C:\n case CTRL_D: {\n // Prevent terminal UI from accepting commands while the process is closing.\n // Without this, fast typers will close the server then start typing their\n // next command and have a bunch of unrelated things pop up.\n pauseInteractions();\n\n const spinners = getAllSpinners();\n spinners.forEach((spinner) => {\n spinner.fail();\n });\n\n const currentProgress = getProgressBar();\n if (currentProgress) {\n currentProgress.terminate();\n setProgressBar(null);\n }\n const spinner = ora({ text: 'Stopping server', color: 'white' }).start();\n try {\n await devServerManager.stopAsync();\n if (options.mcpServer) {\n await options.mcpServer.closeAsync();\n }\n spinner.stopAndPersist({ text: 'Stopped server', symbol: `\\u203A` });\n // @ts-ignore: Argument of type '\"SIGINT\"' is not assignable to parameter of type '\"disconnect\"'.\n process.emit('SIGINT');\n\n // TODO: Is this the right place to do this?\n process.exit();\n } catch (error) {\n spinner.fail('Failed to stop server');\n throw error;\n }\n break;\n }\n case CTRL_L:\n return Log.clear();\n case '?':\n return printUsage(usageOptions, { verbose: true });\n }\n\n // Optionally enabled\n\n if (isWebSocketsEnabled) {\n switch (key) {\n case 'm':\n return actions.toggleDevMenu();\n case 'M':\n return actions.openMoreToolsAsync();\n }\n }\n\n const { platforms = ['ios', 'android', 'web'] } = options;\n\n if (['i', 'a'].includes(key.toLowerCase())) {\n const platform = key.toLowerCase() === 'i' ? 'ios' : 'android';\n\n const shouldPrompt = ['I', 'A'].includes(key);\n if (shouldPrompt) {\n Log.clear();\n }\n\n const server = devServerManager.getDefaultDevServer();\n const settings = PLATFORM_SETTINGS[platform]!;\n\n Log.log(`${BLT} Opening on ${settings.name}...`);\n\n if (server.isTargetingNative() && !platforms.includes(settings.key)) {\n Log.warn(\n chalk`${settings.name} is disabled, enable it by adding {bold ${settings.key}} to the platforms array in your app.json or app.config.js`\n );\n } else {\n try {\n await server.openPlatformAsync(settings.launchTarget, { shouldPrompt });\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n }\n // Break out early.\n return;\n }\n\n switch (key) {\n case 's': {\n Log.clear();\n if (await devServerManager.toggleRuntimeMode()) {\n usageOptions.devClient = devServerManager.options.devClient;\n await actions.printDevServerInfoAsync(usageOptions);\n return;\n }\n break;\n }\n case 'w': {\n try {\n await devServerManager.ensureProjectPrerequisiteAsync(WebSupportProjectPrerequisite);\n if (!platforms.includes('web')) {\n platforms.push('web');\n options.platforms?.push('web');\n }\n } catch (e: any) {\n Log.warn(e.message);\n break;\n }\n\n const isDisabled = !platforms.includes('web');\n if (isDisabled) {\n debug('Web is disabled');\n // Use warnings from the web support setup.\n break;\n }\n\n // Ensure the Webpack dev server is running first\n if (!devServerManager.getWebDevServer()) {\n debug('Starting up webpack dev server');\n await devServerManager.ensureWebDevServerRunningAsync();\n // When this is the first time webpack is started, reprint the connection info.\n await actions.printDevServerInfoAsync(usageOptions);\n }\n\n Log.log(`${BLT} Open in the web browser...`);\n try {\n await devServerManager.getWebDevServer()?.openPlatformAsync('desktop');\n printHelp();\n } catch (error: any) {\n if (!(error instanceof AbortCommandError)) {\n Log.exception(error);\n }\n }\n break;\n }\n case 'c':\n Log.clear();\n await actions.printDevServerInfoAsync(usageOptions);\n return;\n case 'j':\n return actions.openJsInspectorAsync();\n case 'r':\n return actions.reloadApp();\n case 'o':\n Log.log(`${BLT} Opening the editor...`);\n return openInEditorAsync(devServerManager.projectRoot);\n }\n };\n\n const keyPressHandler = new KeyPressHandler(onPressAsync);\n\n const listener = keyPressHandler.createInteractionListener();\n\n addInteractionListener(listener);\n\n // Start observing...\n keyPressHandler.startInterceptingKeyStrokes();\n}\n"],"names":["startInterfaceAsync","debug","require","CTRL_C","CTRL_D","CTRL_L","PLATFORM_SETTINGS","android","name","key","launchTarget","ios","devServerManager","options","dependencyCheckRef","Promise","race","promise","resolve","actions","DevServerManagerActions","isWebSocketsEnabled","getDefaultDevServer","isTargetingNative","usageOptions","devClient","printDevServerInfoAsync","onPressAsync","pauseInteractions","spinners","getAllSpinners","forEach","spinner","fail","currentProgress","getProgressBar","terminate","setProgressBar","ora","text","color","start","stopAsync","mcpServer","closeAsync","stopAndPersist","symbol","process","emit","exit","error","Log","clear","printUsage","verbose","toggleDevMenu","openMoreToolsAsync","platforms","includes","toLowerCase","platform","shouldPrompt","server","settings","log","BLT","warn","chalk","openPlatformAsync","printHelp","AbortCommandError","exception","toggleRuntimeMode","ensureProjectPrerequisiteAsync","WebSupportProjectPrerequisite","push","e","message","isDisabled","getWebDevServer","ensureWebDevServerRunningAsync","openJsInspectorAsync","reloadApp","openInEditorAsync","projectRoot","keyPressHandler","KeyPressHandler","listener","createInteractionListener","addInteractionListener","startInterceptingKeyStrokes"],"mappings":"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"}
@@ -8,34 +8,18 @@ Object.defineProperty(exports, "DevToolsPlugin", {
8
8
  return DevToolsPlugin;
9
9
  }
10
10
  });
11
- function _nodefs() {
12
- const data = /*#__PURE__*/ _interop_require_default(require("node:fs"));
13
- _nodefs = function() {
14
- return data;
15
- };
16
- return data;
17
- }
18
11
  const _DevToolsPluginschema = require("./DevToolsPlugin.schema");
19
12
  const _DevToolsPluginCliExtensionExecutor = require("./DevToolsPluginCliExtensionExecutor");
20
13
  const _DevToolsPluginManager = require("./DevToolsPluginManager");
14
+ const _DevToolsPluginServerHelpers = require("./DevToolsPluginServerHelpers");
21
15
  const _dir = require("../../utils/dir");
22
- function _interop_require_default(obj) {
23
- return obj && obj.__esModule ? obj : {
24
- default: obj
25
- };
26
- }
27
- const maybeRealpath = (target)=>{
28
- try {
29
- return _nodefs().default.realpathSync(target);
30
- } catch {
31
- return target;
32
- }
33
- };
34
16
  class DevToolsPlugin {
35
17
  constructor(plugin, projectRoot){
36
18
  this.plugin = plugin;
37
19
  this.projectRoot = projectRoot;
38
20
  this._executor = undefined;
21
+ this._requestHandler = undefined;
22
+ this._webSocketServers = undefined;
39
23
  const result = _DevToolsPluginschema.PluginSchema.safeParse(plugin);
40
24
  if (!result.success) {
41
25
  throw new Error(`Invalid plugin configuration: ${result.error.message}`, {
@@ -43,11 +27,17 @@ class DevToolsPlugin {
43
27
  });
44
28
  }
45
29
  if (plugin.webpageRoot != null) {
46
- const webpageRoot = maybeRealpath(plugin.webpageRoot);
30
+ const webpageRoot = (0, _dir.maybeRealpathSync)(plugin.webpageRoot) ?? plugin.webpageRoot;
47
31
  if (!(0, _dir.isPathInside)(webpageRoot, plugin.packageRoot)) {
48
32
  throw new Error(`webpageRoot (${plugin.webpageRoot}) is not inside packageRoot (${plugin.packageRoot}).`);
49
33
  }
50
34
  }
35
+ if (plugin.serverEntryPoint != null) {
36
+ const serverEntryPoint = (0, _dir.maybeRealpathSync)(plugin.serverEntryPoint) ?? plugin.serverEntryPoint;
37
+ if (!(0, _dir.isPathInside)(serverEntryPoint, plugin.packageRoot)) {
38
+ throw new Error(`serverEntryPoint (${plugin.serverEntryPoint}) is not inside packageRoot (${plugin.packageRoot}).`);
39
+ }
40
+ }
51
41
  }
52
42
  get packageName() {
53
43
  return this.plugin.packageName;
@@ -56,13 +46,58 @@ class DevToolsPlugin {
56
46
  return this.plugin.packageRoot;
57
47
  }
58
48
  get webpageEndpoint() {
59
- var _this_plugin, _this_plugin1;
60
- return ((_this_plugin = this.plugin) == null ? void 0 : _this_plugin.webpageRoot) ? `${_DevToolsPluginManager.DevToolsPluginEndpoint}/${(_this_plugin1 = this.plugin) == null ? void 0 : _this_plugin1.packageName}` : undefined;
49
+ var _this_plugin, _this_plugin1, _this_plugin2;
50
+ return ((_this_plugin = this.plugin) == null ? void 0 : _this_plugin.webpageRoot) || ((_this_plugin1 = this.plugin) == null ? void 0 : _this_plugin1.serverEntryPoint) ? `${_DevToolsPluginManager.DevToolsPluginEndpoint}/${(_this_plugin2 = this.plugin) == null ? void 0 : _this_plugin2.packageName}` : undefined;
61
51
  }
62
52
  get webpageRoot() {
63
53
  var _this_plugin;
64
54
  return (_this_plugin = this.plugin) == null ? void 0 : _this_plugin.webpageRoot;
65
55
  }
56
+ get serverEntryPoint() {
57
+ var _this_plugin;
58
+ return (_this_plugin = this.plugin) == null ? void 0 : _this_plugin.serverEntryPoint;
59
+ }
60
+ /**
61
+ * Lazily loads the request handler from the plugin's `serverEntryPoint`.
62
+ * The entry point must default-export a handler function
63
+ * (`export default function handler(request) {}` or `module.exports = function handler(request) {}`).
64
+ */ async getRequestHandlerAsync() {
65
+ if (!this.plugin.serverEntryPoint) {
66
+ return undefined;
67
+ }
68
+ if (!this._requestHandler) {
69
+ this._requestHandler = await (0, _DevToolsPluginServerHelpers.loadRequestHandlerAsync)({
70
+ packageName: this.plugin.packageName,
71
+ serverEntryPoint: this.plugin.serverEntryPoint
72
+ });
73
+ }
74
+ return this._requestHandler;
75
+ }
76
+ /**
77
+ * Lazily builds the WebSocket servers contributed by the plugin's `serverEntryPoint`. The entry
78
+ * point exports a `webSocketHandlers` map of route (e.g. `/ws`) to a connection handler; each
79
+ * route becomes a `ws` `WebSocketServer` (in `noServer` mode) that the dev server mounts under
80
+ * `/_expo/plugins/<name>/<route>`. The fetch API based `requestHandler` cannot serve WebSocket
81
+ * upgrades, so this is how a plugin opts into them. Returns an empty object when the plugin
82
+ * exports no handlers.
83
+ */ async getWebSocketServersAsync() {
84
+ if (!this.plugin.serverEntryPoint) {
85
+ return {};
86
+ }
87
+ if (!this._webSocketServers) {
88
+ this._webSocketServers = await (0, _DevToolsPluginServerHelpers.loadWebSocketServerAsync)({
89
+ packageName: this.plugin.packageName,
90
+ serverEntryPoint: this.plugin.serverEntryPoint
91
+ });
92
+ }
93
+ return this._webSocketServers;
94
+ }
95
+ get cliBanner() {
96
+ return this.plugin.bannerTitle !== undefined && this.plugin.bannerTitle !== false;
97
+ }
98
+ get bannerTitle() {
99
+ return typeof this.plugin.bannerTitle === 'string' && this.plugin.bannerTitle ? this.plugin.bannerTitle : this.plugin.packageName;
100
+ }
66
101
  get description() {
67
102
  var _this_plugin_cliExtensions;
68
103
  return ((_this_plugin_cliExtensions = this.plugin.cliExtensions) == null ? void 0 : _this_plugin_cliExtensions.description) ?? '';
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/DevToolsPlugin.ts"],"sourcesContent":["import fs from 'node:fs';\n\nimport type { DevToolsPluginInfo } from './DevToolsPlugin.schema';\nimport { PluginSchema } from './DevToolsPlugin.schema';\nimport { DevToolsPluginCliExtensionExecutor } from './DevToolsPluginCliExtensionExecutor';\nimport { DevToolsPluginEndpoint } from './DevToolsPluginManager';\nimport { isPathInside } from '../../utils/dir';\n\nconst maybeRealpath = (target: string): string => {\n try {\n return fs.realpathSync(target);\n } catch {\n return target;\n }\n};\n\n/**\n * Class that represents a DevTools plugin with CLI and/or web extensions\n *\n * Responsibilities:\n * - Validates plugin configuration against schema\n * - Provides access to plugin metadata (name, description\n * , endpoints)\n * - Manages CLI command execution via DevToolsPluginExecutor\n * - Lazily initializes executor when needed\n * - Constructs web endpoint URLs based on server configuration\n */\nexport class DevToolsPlugin {\n constructor(\n private plugin: DevToolsPluginInfo,\n public readonly projectRoot: string\n ) {\n const result = PluginSchema.safeParse(plugin);\n if (!result.success) {\n throw new Error(`Invalid plugin configuration: ${result.error.message}`, {\n cause: result.error,\n });\n }\n\n if (plugin.webpageRoot != null) {\n const webpageRoot = maybeRealpath(plugin.webpageRoot);\n if (!isPathInside(webpageRoot, plugin.packageRoot)) {\n throw new Error(\n `webpageRoot (${plugin.webpageRoot}) is not inside packageRoot (${plugin.packageRoot}).`\n );\n }\n }\n }\n\n private _executor: DevToolsPluginCliExtensionExecutor | undefined = undefined;\n\n get packageName(): string {\n return this.plugin.packageName;\n }\n\n get packageRoot(): string {\n return this.plugin.packageRoot;\n }\n\n get webpageEndpoint(): string | undefined {\n return this.plugin?.webpageRoot\n ? `${DevToolsPluginEndpoint}/${this.plugin?.packageName}`\n : undefined;\n }\n\n get webpageRoot(): string | undefined {\n return this.plugin?.webpageRoot;\n }\n\n get description(): string {\n return this.plugin.cliExtensions?.description ?? '';\n }\n\n get cliExtensions(): DevToolsPluginInfo['cliExtensions'] {\n return this.plugin.cliExtensions;\n }\n\n get executor(): DevToolsPluginCliExtensionExecutor | undefined {\n if (!this.plugin.cliExtensions?.entryPoint) {\n return undefined;\n }\n\n if (!this._executor) {\n this._executor = new DevToolsPluginCliExtensionExecutor(this.plugin, this.projectRoot);\n }\n\n return this._executor;\n }\n}\n"],"names":["DevToolsPlugin","maybeRealpath","target","fs","realpathSync","plugin","projectRoot","_executor","undefined","result","PluginSchema","safeParse","success","Error","error","message","cause","webpageRoot","isPathInside","packageRoot","packageName","webpageEndpoint","DevToolsPluginEndpoint","description","cliExtensions","executor","entryPoint","DevToolsPluginCliExtensionExecutor"],"mappings":";;;;+BA2BaA;;;eAAAA;;;;gEA3BE;;;;;;sCAGc;oDACsB;uCACZ;qBACV;;;;;;AAE7B,MAAMC,gBAAgB,CAACC;IACrB,IAAI;QACF,OAAOC,iBAAE,CAACC,YAAY,CAACF;IACzB,EAAE,OAAM;QACN,OAAOA;IACT;AACF;AAaO,MAAMF;IACX,YACE,AAAQK,MAA0B,EAClC,AAAgBC,WAAmB,CACnC;aAFQD,SAAAA;aACQC,cAAAA;aAmBVC,YAA4DC;QAjBlE,MAAMC,SAASC,kCAAY,CAACC,SAAS,CAACN;QACtC,IAAI,CAACI,OAAOG,OAAO,EAAE;YACnB,MAAM,IAAIC,MAAM,CAAC,8BAA8B,EAAEJ,OAAOK,KAAK,CAACC,OAAO,EAAE,EAAE;gBACvEC,OAAOP,OAAOK,KAAK;YACrB;QACF;QAEA,IAAIT,OAAOY,WAAW,IAAI,MAAM;YAC9B,MAAMA,cAAchB,cAAcI,OAAOY,WAAW;YACpD,IAAI,CAACC,IAAAA,iBAAY,EAACD,aAAaZ,OAAOc,WAAW,GAAG;gBAClD,MAAM,IAAIN,MACR,CAAC,aAAa,EAAER,OAAOY,WAAW,CAAC,6BAA6B,EAAEZ,OAAOc,WAAW,CAAC,EAAE,CAAC;YAE5F;QACF;IACF;IAIA,IAAIC,cAAsB;QACxB,OAAO,IAAI,CAACf,MAAM,CAACe,WAAW;IAChC;IAEA,IAAID,cAAsB;QACxB,OAAO,IAAI,CAACd,MAAM,CAACc,WAAW;IAChC;IAEA,IAAIE,kBAAsC;YACjC,cAC0B;QADjC,OAAO,EAAA,eAAA,IAAI,CAAChB,MAAM,qBAAX,aAAaY,WAAW,IAC3B,GAAGK,6CAAsB,CAAC,CAAC,GAAE,gBAAA,IAAI,CAACjB,MAAM,qBAAX,cAAae,WAAW,EAAE,GACvDZ;IACN;IAEA,IAAIS,cAAkC;YAC7B;QAAP,QAAO,eAAA,IAAI,CAACZ,MAAM,qBAAX,aAAaY,WAAW;IACjC;IAEA,IAAIM,cAAsB;YACjB;QAAP,OAAO,EAAA,6BAAA,IAAI,CAAClB,MAAM,CAACmB,aAAa,qBAAzB,2BAA2BD,WAAW,KAAI;IACnD;IAEA,IAAIC,gBAAqD;QACvD,OAAO,IAAI,CAACnB,MAAM,CAACmB,aAAa;IAClC;IAEA,IAAIC,WAA2D;YACxD;QAAL,IAAI,GAAC,6BAAA,IAAI,CAACpB,MAAM,CAACmB,aAAa,qBAAzB,2BAA2BE,UAAU,GAAE;YAC1C,OAAOlB;QACT;QAEA,IAAI,CAAC,IAAI,CAACD,SAAS,EAAE;YACnB,IAAI,CAACA,SAAS,GAAG,IAAIoB,sEAAkC,CAAC,IAAI,CAACtB,MAAM,EAAE,IAAI,CAACC,WAAW;QACvF;QAEA,OAAO,IAAI,CAACC,SAAS;IACvB;AACF"}
1
+ {"version":3,"sources":["../../../../src/start/server/DevToolsPlugin.ts"],"sourcesContent":["import type { WebSocketServer } from 'ws';\n\nimport type { DevToolsPluginInfo } from './DevToolsPlugin.schema';\nimport { PluginSchema } from './DevToolsPlugin.schema';\nimport { DevToolsPluginCliExtensionExecutor } from './DevToolsPluginCliExtensionExecutor';\nimport { DevToolsPluginEndpoint } from './DevToolsPluginManager';\nimport {\n type DevToolsPluginRequestHandler,\n loadRequestHandlerAsync,\n loadWebSocketServerAsync,\n} from './DevToolsPluginServerHelpers';\nimport { isPathInside, maybeRealpathSync } from '../../utils/dir';\n\nexport type { DevToolsPluginRequestHandler } from './DevToolsPluginServerHelpers';\n\n/**\n * Class that represents a DevTools plugin with CLI and/or web extensions\n *\n * Responsibilities:\n * - Validates plugin configuration against schema\n * - Provides access to plugin metadata (name, description\n * , endpoints)\n * - Manages CLI command execution via DevToolsPluginExecutor\n * - Lazily initializes executor when needed\n * - Constructs web endpoint URLs based on server configuration\n */\nexport class DevToolsPlugin {\n constructor(\n private plugin: DevToolsPluginInfo,\n public readonly projectRoot: string\n ) {\n const result = PluginSchema.safeParse(plugin);\n if (!result.success) {\n throw new Error(`Invalid plugin configuration: ${result.error.message}`, {\n cause: result.error,\n });\n }\n\n if (plugin.webpageRoot != null) {\n const webpageRoot = maybeRealpathSync(plugin.webpageRoot) ?? plugin.webpageRoot;\n if (!isPathInside(webpageRoot, plugin.packageRoot)) {\n throw new Error(\n `webpageRoot (${plugin.webpageRoot}) is not inside packageRoot (${plugin.packageRoot}).`\n );\n }\n }\n\n if (plugin.serverEntryPoint != null) {\n const serverEntryPoint =\n maybeRealpathSync(plugin.serverEntryPoint) ?? plugin.serverEntryPoint;\n if (!isPathInside(serverEntryPoint, plugin.packageRoot)) {\n throw new Error(\n `serverEntryPoint (${plugin.serverEntryPoint}) is not inside packageRoot (${plugin.packageRoot}).`\n );\n }\n }\n }\n\n private _executor: DevToolsPluginCliExtensionExecutor | undefined = undefined;\n private _requestHandler: DevToolsPluginRequestHandler | undefined = undefined;\n private _webSocketServers: Record<string, WebSocketServer> | undefined = undefined;\n\n get packageName(): string {\n return this.plugin.packageName;\n }\n\n get packageRoot(): string {\n return this.plugin.packageRoot;\n }\n\n get webpageEndpoint(): string | undefined {\n return this.plugin?.webpageRoot || this.plugin?.serverEntryPoint\n ? `${DevToolsPluginEndpoint}/${this.plugin?.packageName}`\n : undefined;\n }\n\n get webpageRoot(): string | undefined {\n return this.plugin?.webpageRoot;\n }\n\n get serverEntryPoint(): string | undefined {\n return this.plugin?.serverEntryPoint;\n }\n\n /**\n * Lazily loads the request handler from the plugin's `serverEntryPoint`.\n * The entry point must default-export a handler function\n * (`export default function handler(request) {}` or `module.exports = function handler(request) {}`).\n */\n async getRequestHandlerAsync(): Promise<DevToolsPluginRequestHandler | undefined> {\n if (!this.plugin.serverEntryPoint) {\n return undefined;\n }\n\n if (!this._requestHandler) {\n this._requestHandler = await loadRequestHandlerAsync({\n packageName: this.plugin.packageName,\n serverEntryPoint: this.plugin.serverEntryPoint,\n });\n }\n\n return this._requestHandler;\n }\n\n /**\n * Lazily builds the WebSocket servers contributed by the plugin's `serverEntryPoint`. The entry\n * point exports a `webSocketHandlers` map of route (e.g. `/ws`) to a connection handler; each\n * route becomes a `ws` `WebSocketServer` (in `noServer` mode) that the dev server mounts under\n * `/_expo/plugins/<name>/<route>`. The fetch API based `requestHandler` cannot serve WebSocket\n * upgrades, so this is how a plugin opts into them. Returns an empty object when the plugin\n * exports no handlers.\n */\n async getWebSocketServersAsync(): Promise<Record<string, WebSocketServer>> {\n if (!this.plugin.serverEntryPoint) {\n return {};\n }\n\n if (!this._webSocketServers) {\n this._webSocketServers = await loadWebSocketServerAsync({\n packageName: this.plugin.packageName,\n serverEntryPoint: this.plugin.serverEntryPoint,\n });\n }\n\n return this._webSocketServers;\n }\n\n get cliBanner(): boolean {\n return this.plugin.bannerTitle !== undefined && this.plugin.bannerTitle !== false;\n }\n\n get bannerTitle(): string {\n return typeof this.plugin.bannerTitle === 'string' && this.plugin.bannerTitle\n ? this.plugin.bannerTitle\n : this.plugin.packageName;\n }\n\n get description(): string {\n return this.plugin.cliExtensions?.description ?? '';\n }\n\n get cliExtensions(): DevToolsPluginInfo['cliExtensions'] {\n return this.plugin.cliExtensions;\n }\n\n get executor(): DevToolsPluginCliExtensionExecutor | undefined {\n if (!this.plugin.cliExtensions?.entryPoint) {\n return undefined;\n }\n\n if (!this._executor) {\n this._executor = new DevToolsPluginCliExtensionExecutor(this.plugin, this.projectRoot);\n }\n\n return this._executor;\n }\n}\n"],"names":["DevToolsPlugin","plugin","projectRoot","_executor","undefined","_requestHandler","_webSocketServers","result","PluginSchema","safeParse","success","Error","error","message","cause","webpageRoot","maybeRealpathSync","isPathInside","packageRoot","serverEntryPoint","packageName","webpageEndpoint","DevToolsPluginEndpoint","getRequestHandlerAsync","loadRequestHandlerAsync","getWebSocketServersAsync","loadWebSocketServerAsync","cliBanner","bannerTitle","description","cliExtensions","executor","entryPoint","DevToolsPluginCliExtensionExecutor"],"mappings":"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"}
@@ -50,6 +50,11 @@ const PluginSchema = _zod().z.object({
50
50
  packageName: _zod().z.string().min(1),
51
51
  packageRoot: _zod().z.string().min(1),
52
52
  webpageRoot: _zod().z.string().optional(),
53
+ bannerTitle: _zod().z.union([
54
+ _zod().z.boolean(),
55
+ _zod().z.string().min(1)
56
+ ]).optional(),
57
+ serverEntryPoint: _zod().z.string().optional(),
53
58
  cliExtensions: CliExtensionsSchema.optional()
54
59
  });
55
60
  const DevToolsPluginOutputLinesSchema = _zod().z.union([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/DevToolsPlugin.schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nconst CommandParameterSchema = z.object({\n name: z.string().min(1),\n type: z.enum(['text', 'number', 'confirm']),\n description: z.string().optional(),\n});\n\nexport type DevToolsPluginCommandParameter = z.infer<typeof CommandParameterSchema>;\n\nconst CommandSchema = z.object({\n name: z.string().min(1),\n title: z.string().min(1),\n environments: z.array(z.enum(['cli', 'mcp'])).readonly(),\n parameters: z.array(CommandParameterSchema).optional(),\n});\n\nexport type DevToolsPluginCommand = z.infer<typeof CommandSchema>;\n\nexport type DevToolsPluginExecutorArguments = {\n command: string;\n metroServerOrigin: string;\n args?: Record<string, string | number | boolean> | undefined;\n onOutput?: (output: DevToolsPluginOutput) => void;\n};\n\nconst CliExtensionsSchema = z.object({\n description: z.string(),\n commands: z.array(CommandSchema).min(1),\n entryPoint: z.string().min(1),\n});\n\nexport type DevToolsPluginCliExtensions = z.infer<typeof CliExtensionsSchema>;\n\nexport const PluginSchema = z.object({\n packageName: z.string().min(1),\n packageRoot: z.string().min(1),\n webpageRoot: z.string().optional(),\n cliExtensions: CliExtensionsSchema.optional(),\n});\n\nexport type DevToolsPluginInfo = z.infer<typeof PluginSchema>;\n\nconst DevToolsPluginOutputLinesSchema = z.union([\n z.object({\n type: z.literal('text'),\n text: z.string(),\n url: z.string().optional(),\n level: z.enum(['info', 'warning', 'error']),\n }),\n z.object({\n type: z.literal('audio'),\n url: z.string().url(),\n text: z.string().optional(),\n }),\n z.object({\n type: z.literal('image'),\n url: z.string().url(),\n text: z.string().optional(),\n }),\n]);\n\nexport const DevToolsPluginOutputSchema = z.array(DevToolsPluginOutputLinesSchema);\n\nexport type DevToolsPluginOutput = z.infer<typeof DevToolsPluginOutputSchema>;\n"],"names":["DevToolsPluginOutputSchema","PluginSchema","CommandParameterSchema","z","object","name","string","min","type","enum","description","optional","CommandSchema","title","environments","array","readonly","parameters","CliExtensionsSchema","commands","entryPoint","packageName","packageRoot","webpageRoot","cliExtensions","DevToolsPluginOutputLinesSchema","union","literal","text","url","level"],"mappings":";;;;;;;;;;;QA8DaA;eAAAA;;QA5BAC;eAAAA;;;;yBAlCK;;;;;;AAElB,MAAMC,yBAAyBC,QAAC,CAACC,MAAM,CAAC;IACtCC,MAAMF,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACrBC,MAAML,QAAC,CAACM,IAAI,CAAC;QAAC;QAAQ;QAAU;KAAU;IAC1CC,aAAaP,QAAC,CAACG,MAAM,GAAGK,QAAQ;AAClC;AAIA,MAAMC,gBAAgBT,QAAC,CAACC,MAAM,CAAC;IAC7BC,MAAMF,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACrBM,OAAOV,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACtBO,cAAcX,QAAC,CAACY,KAAK,CAACZ,QAAC,CAACM,IAAI,CAAC;QAAC;QAAO;KAAM,GAAGO,QAAQ;IACtDC,YAAYd,QAAC,CAACY,KAAK,CAACb,wBAAwBS,QAAQ;AACtD;AAWA,MAAMO,sBAAsBf,QAAC,CAACC,MAAM,CAAC;IACnCM,aAAaP,QAAC,CAACG,MAAM;IACrBa,UAAUhB,QAAC,CAACY,KAAK,CAACH,eAAeL,GAAG,CAAC;IACrCa,YAAYjB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;AAC7B;AAIO,MAAMN,eAAeE,QAAC,CAACC,MAAM,CAAC;IACnCiB,aAAalB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IAC5Be,aAAanB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IAC5BgB,aAAapB,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAChCa,eAAeN,oBAAoBP,QAAQ;AAC7C;AAIA,MAAMc,kCAAkCtB,QAAC,CAACuB,KAAK,CAAC;IAC9CvB,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAACwB,OAAO,CAAC;QAChBC,MAAMzB,QAAC,CAACG,MAAM;QACduB,KAAK1B,QAAC,CAACG,MAAM,GAAGK,QAAQ;QACxBmB,OAAO3B,QAAC,CAACM,IAAI,CAAC;YAAC;YAAQ;YAAW;SAAQ;IAC5C;IACAN,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAACwB,OAAO,CAAC;QAChBE,KAAK1B,QAAC,CAACG,MAAM,GAAGuB,GAAG;QACnBD,MAAMzB,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAC3B;IACAR,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAACwB,OAAO,CAAC;QAChBE,KAAK1B,QAAC,CAACG,MAAM,GAAGuB,GAAG;QACnBD,MAAMzB,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAC3B;CACD;AAEM,MAAMX,6BAA6BG,QAAC,CAACY,KAAK,CAACU"}
1
+ {"version":3,"sources":["../../../../src/start/server/DevToolsPlugin.schema.ts"],"sourcesContent":["import { z } from 'zod';\n\nconst CommandParameterSchema = z.object({\n name: z.string().min(1),\n type: z.enum(['text', 'number', 'confirm']),\n description: z.string().optional(),\n});\n\nexport type DevToolsPluginCommandParameter = z.infer<typeof CommandParameterSchema>;\n\nconst CommandSchema = z.object({\n name: z.string().min(1),\n title: z.string().min(1),\n environments: z.array(z.enum(['cli', 'mcp'])).readonly(),\n parameters: z.array(CommandParameterSchema).optional(),\n});\n\nexport type DevToolsPluginCommand = z.infer<typeof CommandSchema>;\n\nexport type DevToolsPluginExecutorArguments = {\n command: string;\n metroServerOrigin: string;\n args?: Record<string, string | number | boolean> | undefined;\n onOutput?: (output: DevToolsPluginOutput) => void;\n};\n\nconst CliExtensionsSchema = z.object({\n description: z.string(),\n commands: z.array(CommandSchema).min(1),\n entryPoint: z.string().min(1),\n});\n\nexport type DevToolsPluginCliExtensions = z.infer<typeof CliExtensionsSchema>;\n\nexport const PluginSchema = z.object({\n packageName: z.string().min(1),\n packageRoot: z.string().min(1),\n webpageRoot: z.string().optional(),\n bannerTitle: z.union([z.boolean(), z.string().min(1)]).optional(),\n serverEntryPoint: z.string().optional(),\n cliExtensions: CliExtensionsSchema.optional(),\n});\n\nexport type DevToolsPluginInfo = z.infer<typeof PluginSchema>;\n\nconst DevToolsPluginOutputLinesSchema = z.union([\n z.object({\n type: z.literal('text'),\n text: z.string(),\n url: z.string().optional(),\n level: z.enum(['info', 'warning', 'error']),\n }),\n z.object({\n type: z.literal('audio'),\n url: z.string().url(),\n text: z.string().optional(),\n }),\n z.object({\n type: z.literal('image'),\n url: z.string().url(),\n text: z.string().optional(),\n }),\n]);\n\nexport const DevToolsPluginOutputSchema = z.array(DevToolsPluginOutputLinesSchema);\n\nexport type DevToolsPluginOutput = z.infer<typeof DevToolsPluginOutputSchema>;\n"],"names":["DevToolsPluginOutputSchema","PluginSchema","CommandParameterSchema","z","object","name","string","min","type","enum","description","optional","CommandSchema","title","environments","array","readonly","parameters","CliExtensionsSchema","commands","entryPoint","packageName","packageRoot","webpageRoot","bannerTitle","union","boolean","serverEntryPoint","cliExtensions","DevToolsPluginOutputLinesSchema","literal","text","url","level"],"mappings":";;;;;;;;;;;QAgEaA;eAAAA;;QA9BAC;eAAAA;;;;yBAlCK;;;;;;AAElB,MAAMC,yBAAyBC,QAAC,CAACC,MAAM,CAAC;IACtCC,MAAMF,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACrBC,MAAML,QAAC,CAACM,IAAI,CAAC;QAAC;QAAQ;QAAU;KAAU;IAC1CC,aAAaP,QAAC,CAACG,MAAM,GAAGK,QAAQ;AAClC;AAIA,MAAMC,gBAAgBT,QAAC,CAACC,MAAM,CAAC;IAC7BC,MAAMF,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACrBM,OAAOV,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IACtBO,cAAcX,QAAC,CAACY,KAAK,CAACZ,QAAC,CAACM,IAAI,CAAC;QAAC;QAAO;KAAM,GAAGO,QAAQ;IACtDC,YAAYd,QAAC,CAACY,KAAK,CAACb,wBAAwBS,QAAQ;AACtD;AAWA,MAAMO,sBAAsBf,QAAC,CAACC,MAAM,CAAC;IACnCM,aAAaP,QAAC,CAACG,MAAM;IACrBa,UAAUhB,QAAC,CAACY,KAAK,CAACH,eAAeL,GAAG,CAAC;IACrCa,YAAYjB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;AAC7B;AAIO,MAAMN,eAAeE,QAAC,CAACC,MAAM,CAAC;IACnCiB,aAAalB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IAC5Be,aAAanB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;IAC5BgB,aAAapB,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAChCa,aAAarB,QAAC,CAACsB,KAAK,CAAC;QAACtB,QAAC,CAACuB,OAAO;QAAIvB,QAAC,CAACG,MAAM,GAAGC,GAAG,CAAC;KAAG,EAAEI,QAAQ;IAC/DgB,kBAAkBxB,QAAC,CAACG,MAAM,GAAGK,QAAQ;IACrCiB,eAAeV,oBAAoBP,QAAQ;AAC7C;AAIA,MAAMkB,kCAAkC1B,QAAC,CAACsB,KAAK,CAAC;IAC9CtB,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAAC2B,OAAO,CAAC;QAChBC,MAAM5B,QAAC,CAACG,MAAM;QACd0B,KAAK7B,QAAC,CAACG,MAAM,GAAGK,QAAQ;QACxBsB,OAAO9B,QAAC,CAACM,IAAI,CAAC;YAAC;YAAQ;YAAW;SAAQ;IAC5C;IACAN,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAAC2B,OAAO,CAAC;QAChBE,KAAK7B,QAAC,CAACG,MAAM,GAAG0B,GAAG;QACnBD,MAAM5B,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAC3B;IACAR,QAAC,CAACC,MAAM,CAAC;QACPI,MAAML,QAAC,CAAC2B,OAAO,CAAC;QAChBE,KAAK7B,QAAC,CAACG,MAAM,GAAG0B,GAAG;QACnBD,MAAM5B,QAAC,CAACG,MAAM,GAAGK,QAAQ;IAC3B;CACD;AAEM,MAAMX,6BAA6BG,QAAC,CAACY,KAAK,CAACc"}
@@ -14,12 +14,19 @@ _export(exports, {
14
14
  },
15
15
  get default () {
16
16
  return DevToolsPluginManager;
17
+ },
18
+ get event () {
19
+ return event;
17
20
  }
18
21
  });
19
22
  const _DevToolsPlugin = require("./DevToolsPlugin");
23
+ const _events = require("../../events");
20
24
  const _log = require("../../log");
21
25
  const debug = require('debug')('expo:start:server:devtools');
22
26
  const DevToolsPluginEndpoint = '/_expo/plugins';
27
+ const event = (0, _events.events)('expo', (t)=>[
28
+ t.event()
29
+ ]);
23
30
  class DevToolsPluginManager {
24
31
  constructor(projectRoot){
25
32
  this.projectRoot = projectRoot;
@@ -28,13 +35,20 @@ class DevToolsPluginManager {
28
35
  async queryPluginsAsync() {
29
36
  if (!this.plugins) {
30
37
  this.plugins = await this.queryAutolinkedPluginsAsync(this.projectRoot);
38
+ event('dev-tools-plugin:load', {
39
+ plugins: this.plugins.map((plugin)=>({
40
+ packageName: plugin.packageName,
41
+ bannerTitle: plugin.bannerTitle,
42
+ cliBanner: plugin.cliBanner,
43
+ webpageEndpoint: plugin.webpageEndpoint
44
+ }))
45
+ });
31
46
  }
32
47
  return this.plugins;
33
48
  }
34
- async queryPluginWebpageRootAsync(pluginName) {
49
+ async queryPluginAsync(pluginName) {
35
50
  const plugins = await this.queryPluginsAsync();
36
- const plugin = plugins.find((p)=>p.packageName === pluginName);
37
- return (plugin == null ? void 0 : plugin.webpageRoot) ?? null;
51
+ return plugins.find((p)=>p.packageName === pluginName) ?? null;
38
52
  }
39
53
  async queryAutolinkedPluginsAsync(projectRoot) {
40
54
  const autolinking = require('expo/internal/unstable-autolinking-exports');
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/start/server/DevToolsPluginManager.ts"],"sourcesContent":["import type { ModuleDescriptorDevTools } from 'expo-modules-autolinking/exports';\n\nimport { DevToolsPlugin } from './DevToolsPlugin';\nimport { Log } from '../../log';\n\nconst debug = require('debug')('expo:start:server:devtools');\n\nexport const DevToolsPluginEndpoint = '/_expo/plugins';\n\nexport default class DevToolsPluginManager {\n private plugins: DevToolsPlugin[] | null = null;\n\n constructor(private projectRoot: string) {}\n\n public async queryPluginsAsync(): Promise<DevToolsPlugin[]> {\n if (!this.plugins) {\n this.plugins = await this.queryAutolinkedPluginsAsync(this.projectRoot);\n }\n return this.plugins;\n }\n\n public async queryPluginWebpageRootAsync(pluginName: string): Promise<string | null> {\n const plugins = await this.queryPluginsAsync();\n const plugin = plugins.find((p) => p.packageName === pluginName);\n return plugin?.webpageRoot ?? null;\n }\n\n private async queryAutolinkedPluginsAsync(projectRoot: string): Promise<DevToolsPlugin[]> {\n const autolinking: typeof import('expo/internal/unstable-autolinking-exports') = require('expo/internal/unstable-autolinking-exports');\n const linker = autolinking.makeCachedDependenciesLinker({ projectRoot });\n const revisions = await autolinking.scanExpoModuleResolutionsForPlatform(linker, 'devtools');\n const { resolveModuleAsync } = autolinking.getLinkingImplementationForPlatform('devtools');\n const plugins: ModuleDescriptorDevTools[] = (\n await Promise.all(\n Object.values(revisions).map((revision) => resolveModuleAsync(revision.name, revision))\n )\n ).filter((maybePlugin) => maybePlugin != null);\n debug('Found autolinked plugins', plugins);\n return plugins\n .map((pluginInfo) => {\n try {\n return new DevToolsPlugin(pluginInfo, this.projectRoot);\n } catch (error: any) {\n Log.warn(\n `Skipping plugin \"${pluginInfo.packageName}\": ${error.message ?? 'invalid configuration'}`\n );\n debug('Plugin validation error for %s: %O', pluginInfo.packageName, error);\n return null;\n }\n })\n .filter((p) => p != null) as DevToolsPlugin[];\n }\n}\n"],"names":["DevToolsPluginEndpoint","DevToolsPluginManager","debug","require","projectRoot","plugins","queryPluginsAsync","queryAutolinkedPluginsAsync","queryPluginWebpageRootAsync","pluginName","plugin","find","p","packageName","webpageRoot","autolinking","linker","makeCachedDependenciesLinker","revisions","scanExpoModuleResolutionsForPlatform","resolveModuleAsync","getLinkingImplementationForPlatform","Promise","all","Object","values","map","revision","name","filter","maybePlugin","pluginInfo","DevToolsPlugin","error","Log","warn","message"],"mappings":";;;;;;;;;;;QAOaA;eAAAA;;QAEb;eAAqBC;;;gCAPU;qBACX;AAEpB,MAAMC,QAAQC,QAAQ,SAAS;AAExB,MAAMH,yBAAyB;AAEvB,MAAMC;IAGnB,YAAY,AAAQG,WAAmB,CAAE;aAArBA,cAAAA;aAFZC,UAAmC;IAED;IAE1C,MAAaC,oBAA+C;QAC1D,IAAI,CAAC,IAAI,CAACD,OAAO,EAAE;YACjB,IAAI,CAACA,OAAO,GAAG,MAAM,IAAI,CAACE,2BAA2B,CAAC,IAAI,CAACH,WAAW;QACxE;QACA,OAAO,IAAI,CAACC,OAAO;IACrB;IAEA,MAAaG,4BAA4BC,UAAkB,EAA0B;QACnF,MAAMJ,UAAU,MAAM,IAAI,CAACC,iBAAiB;QAC5C,MAAMI,SAASL,QAAQM,IAAI,CAAC,CAACC,IAAMA,EAAEC,WAAW,KAAKJ;QACrD,OAAOC,CAAAA,0BAAAA,OAAQI,WAAW,KAAI;IAChC;IAEA,MAAcP,4BAA4BH,WAAmB,EAA6B;QACxF,MAAMW,cAA2EZ,QAAQ;QACzF,MAAMa,SAASD,YAAYE,4BAA4B,CAAC;YAAEb;QAAY;QACtE,MAAMc,YAAY,MAAMH,YAAYI,oCAAoC,CAACH,QAAQ;QACjF,MAAM,EAAEI,kBAAkB,EAAE,GAAGL,YAAYM,mCAAmC,CAAC;QAC/E,MAAMhB,UAAsC,AAC1C,CAAA,MAAMiB,QAAQC,GAAG,CACfC,OAAOC,MAAM,CAACP,WAAWQ,GAAG,CAAC,CAACC,WAAaP,mBAAmBO,SAASC,IAAI,EAAED,WAC/E,EACAE,MAAM,CAAC,CAACC,cAAgBA,eAAe;QACzC5B,MAAM,4BAA4BG;QAClC,OAAOA,QACJqB,GAAG,CAAC,CAACK;YACJ,IAAI;gBACF,OAAO,IAAIC,8BAAc,CAACD,YAAY,IAAI,CAAC3B,WAAW;YACxD,EAAE,OAAO6B,OAAY;gBACnBC,QAAG,CAACC,IAAI,CACN,CAAC,iBAAiB,EAAEJ,WAAWlB,WAAW,CAAC,GAAG,EAAEoB,MAAMG,OAAO,IAAI,yBAAyB;gBAE5FlC,MAAM,sCAAsC6B,WAAWlB,WAAW,EAAEoB;gBACpE,OAAO;YACT;QACF,GACCJ,MAAM,CAAC,CAACjB,IAAMA,KAAK;IACxB;AACF"}
1
+ {"version":3,"sources":["../../../../src/start/server/DevToolsPluginManager.ts"],"sourcesContent":["import type { ModuleDescriptorDevTools } from 'expo-modules-autolinking/exports';\n\nimport { DevToolsPlugin } from './DevToolsPlugin';\nimport { events } from '../../events';\nimport { Log } from '../../log';\n\nconst debug = require('debug')('expo:start:server:devtools');\n\nexport const DevToolsPluginEndpoint = '/_expo/plugins';\n\nexport const event = events('expo', (t) => [\n t.event<\n 'dev-tools-plugin:load',\n {\n plugins: {\n packageName: string;\n bannerTitle: string;\n cliBanner: boolean;\n webpageEndpoint: string | undefined;\n }[];\n }\n >(),\n]);\n\nexport default class DevToolsPluginManager {\n private plugins: DevToolsPlugin[] | null = null;\n\n constructor(private projectRoot: string) {}\n\n public async queryPluginsAsync(): Promise<DevToolsPlugin[]> {\n if (!this.plugins) {\n this.plugins = await this.queryAutolinkedPluginsAsync(this.projectRoot);\n event('dev-tools-plugin:load', {\n plugins: this.plugins.map((plugin) => ({\n packageName: plugin.packageName,\n bannerTitle: plugin.bannerTitle,\n cliBanner: plugin.cliBanner,\n webpageEndpoint: plugin.webpageEndpoint,\n })),\n });\n }\n return this.plugins;\n }\n\n public async queryPluginAsync(pluginName: string): Promise<DevToolsPlugin | null> {\n const plugins = await this.queryPluginsAsync();\n return plugins.find((p) => p.packageName === pluginName) ?? null;\n }\n\n private async queryAutolinkedPluginsAsync(projectRoot: string): Promise<DevToolsPlugin[]> {\n const autolinking: typeof import('expo/internal/unstable-autolinking-exports') = require('expo/internal/unstable-autolinking-exports');\n const linker = autolinking.makeCachedDependenciesLinker({ projectRoot });\n const revisions = await autolinking.scanExpoModuleResolutionsForPlatform(linker, 'devtools');\n const { resolveModuleAsync } = autolinking.getLinkingImplementationForPlatform('devtools');\n const plugins: ModuleDescriptorDevTools[] = (\n await Promise.all(\n Object.values(revisions).map((revision) => resolveModuleAsync(revision.name, revision))\n )\n ).filter((maybePlugin) => maybePlugin != null);\n debug('Found autolinked plugins', plugins);\n return plugins\n .map((pluginInfo) => {\n try {\n return new DevToolsPlugin(pluginInfo, this.projectRoot);\n } catch (error: any) {\n Log.warn(\n `Skipping plugin \"${pluginInfo.packageName}\": ${error.message ?? 'invalid configuration'}`\n );\n debug('Plugin validation error for %s: %O', pluginInfo.packageName, error);\n return null;\n }\n })\n .filter((p) => p != null) as DevToolsPlugin[];\n }\n}\n"],"names":["DevToolsPluginEndpoint","DevToolsPluginManager","event","debug","require","events","t","projectRoot","plugins","queryPluginsAsync","queryAutolinkedPluginsAsync","map","plugin","packageName","bannerTitle","cliBanner","webpageEndpoint","queryPluginAsync","pluginName","find","p","autolinking","linker","makeCachedDependenciesLinker","revisions","scanExpoModuleResolutionsForPlatform","resolveModuleAsync","getLinkingImplementationForPlatform","Promise","all","Object","values","revision","name","filter","maybePlugin","pluginInfo","DevToolsPlugin","error","Log","warn","message"],"mappings":";;;;;;;;;;;QAQaA;eAAAA;;QAgBb;eAAqBC;;QAdRC;eAAAA;;;gCARkB;wBACR;qBACH;AAEpB,MAAMC,QAAQC,QAAQ,SAAS;AAExB,MAAMJ,yBAAyB;AAE/B,MAAME,QAAQG,IAAAA,cAAM,EAAC,QAAQ,CAACC,IAAM;QACzCA,EAAEJ,KAAK;KAWR;AAEc,MAAMD;IAGnB,YAAY,AAAQM,WAAmB,CAAE;aAArBA,cAAAA;aAFZC,UAAmC;IAED;IAE1C,MAAaC,oBAA+C;QAC1D,IAAI,CAAC,IAAI,CAACD,OAAO,EAAE;YACjB,IAAI,CAACA,OAAO,GAAG,MAAM,IAAI,CAACE,2BAA2B,CAAC,IAAI,CAACH,WAAW;YACtEL,MAAM,yBAAyB;gBAC7BM,SAAS,IAAI,CAACA,OAAO,CAACG,GAAG,CAAC,CAACC,SAAY,CAAA;wBACrCC,aAAaD,OAAOC,WAAW;wBAC/BC,aAAaF,OAAOE,WAAW;wBAC/BC,WAAWH,OAAOG,SAAS;wBAC3BC,iBAAiBJ,OAAOI,eAAe;oBACzC,CAAA;YACF;QACF;QACA,OAAO,IAAI,CAACR,OAAO;IACrB;IAEA,MAAaS,iBAAiBC,UAAkB,EAAkC;QAChF,MAAMV,UAAU,MAAM,IAAI,CAACC,iBAAiB;QAC5C,OAAOD,QAAQW,IAAI,CAAC,CAACC,IAAMA,EAAEP,WAAW,KAAKK,eAAe;IAC9D;IAEA,MAAcR,4BAA4BH,WAAmB,EAA6B;QACxF,MAAMc,cAA2EjB,QAAQ;QACzF,MAAMkB,SAASD,YAAYE,4BAA4B,CAAC;YAAEhB;QAAY;QACtE,MAAMiB,YAAY,MAAMH,YAAYI,oCAAoC,CAACH,QAAQ;QACjF,MAAM,EAAEI,kBAAkB,EAAE,GAAGL,YAAYM,mCAAmC,CAAC;QAC/E,MAAMnB,UAAsC,AAC1C,CAAA,MAAMoB,QAAQC,GAAG,CACfC,OAAOC,MAAM,CAACP,WAAWb,GAAG,CAAC,CAACqB,WAAaN,mBAAmBM,SAASC,IAAI,EAAED,WAC/E,EACAE,MAAM,CAAC,CAACC,cAAgBA,eAAe;QACzChC,MAAM,4BAA4BK;QAClC,OAAOA,QACJG,GAAG,CAAC,CAACyB;YACJ,IAAI;gBACF,OAAO,IAAIC,8BAAc,CAACD,YAAY,IAAI,CAAC7B,WAAW;YACxD,EAAE,OAAO+B,OAAY;gBACnBC,QAAG,CAACC,IAAI,CACN,CAAC,iBAAiB,EAAEJ,WAAWvB,WAAW,CAAC,GAAG,EAAEyB,MAAMG,OAAO,IAAI,yBAAyB;gBAE5FtC,MAAM,sCAAsCiC,WAAWvB,WAAW,EAAEyB;gBACpE,OAAO;YACT;QACF,GACCJ,MAAM,CAAC,CAACd,IAAMA,KAAK;IACxB;AACF"}