@expo/cli 54.0.8-canary-20250919-7a31b96 → 54.1.0-canary-20250930-9dc59d3

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 (35) hide show
  1. package/build/bin/cli +1 -1
  2. package/build/src/start/doctor/dependencies/getVersionedPackages.js +0 -4
  3. package/build/src/start/doctor/dependencies/getVersionedPackages.js.map +1 -1
  4. package/build/src/start/doctor/dependencies/validateDependenciesVersions.js +3 -0
  5. package/build/src/start/doctor/dependencies/validateDependenciesVersions.js.map +1 -1
  6. package/build/src/start/interface/cliExtensionMenuItemHandler.js +173 -0
  7. package/build/src/start/interface/cliExtensionMenuItemHandler.js.map +1 -0
  8. package/build/src/start/interface/createDevToolsMenuItems.js +159 -0
  9. package/build/src/start/interface/createDevToolsMenuItems.js.map +1 -0
  10. package/build/src/start/interface/interactiveActions.js +8 -12
  11. package/build/src/start/interface/interactiveActions.js.map +1 -1
  12. package/build/src/start/platforms/android/adb.js +1 -1
  13. package/build/src/start/platforms/android/adb.js.map +1 -1
  14. package/build/src/start/server/DevToolsPlugin.js +60 -0
  15. package/build/src/start/server/DevToolsPlugin.js.map +1 -0
  16. package/build/src/start/server/DevToolsPlugin.schema.js +79 -0
  17. package/build/src/start/server/DevToolsPlugin.schema.js.map +1 -0
  18. package/build/src/start/server/DevToolsPluginCliExtensionExecutor.js +119 -0
  19. package/build/src/start/server/DevToolsPluginCliExtensionExecutor.js.map +1 -0
  20. package/build/src/start/server/DevToolsPluginCliExtensionResults.js +61 -0
  21. package/build/src/start/server/DevToolsPluginCliExtensionResults.js.map +1 -0
  22. package/build/src/start/server/DevToolsPluginManager.js +4 -8
  23. package/build/src/start/server/DevToolsPluginManager.js.map +1 -1
  24. package/build/src/start/server/metro/MetroBundlerDevServer.js +125 -9
  25. package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
  26. package/build/src/start/server/metro/createServerRouteMiddleware.js +6 -5
  27. package/build/src/start/server/metro/createServerRouteMiddleware.js.map +1 -1
  28. package/build/src/start/server/metro/externals.js +1 -0
  29. package/build/src/start/server/metro/externals.js.map +1 -1
  30. package/build/src/start/server/metro/router.js.map +1 -1
  31. package/build/src/start/server/middleware/DataLoaderModuleMiddleware.js +75 -0
  32. package/build/src/start/server/middleware/DataLoaderModuleMiddleware.js.map +1 -0
  33. package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
  34. package/build/src/utils/telemetry/utils/context.js +1 -1
  35. package/package.json +19 -18
package/build/bin/cli CHANGED
@@ -123,7 +123,7 @@ const args = (0, _arg().default)({
123
123
  });
124
124
  if (args['--version']) {
125
125
  // Version is added in the build script.
126
- console.log("54.0.8-canary-20250919-7a31b96");
126
+ console.log("54.1.0-canary-20250930-9dc59d3");
127
127
  process.exit(0);
128
128
  }
129
129
  if (args['--non-interactive']) {
@@ -65,10 +65,6 @@ async function getCombinedKnownVersionsAsync({ projectRoot, sdkVersion, skipCach
65
65
  if (skipRemoteVersions) {
66
66
  _log.Log.warn('Dependency validation might be unreliable when using canary SDK versions');
67
67
  }
68
- if (_env.env.EXPO_NO_DEPENDENCY_VALIDATION) {
69
- debug('Dependency validation is disabled through EXPO_NO_DEPENDENCY_VALIDATION=1');
70
- return {};
71
- }
72
68
  const bundledNativeModules = sdkVersion ? await (0, _bundledNativeModules.getVersionedNativeModulesAsync)(projectRoot, sdkVersion, {
73
69
  skipRemoteVersions
74
70
  }) : {};
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/doctor/dependencies/getVersionedPackages.ts"],"sourcesContent":["import { PackageJSONConfig } from '@expo/config';\nimport npmPackageArg from 'npm-package-arg';\n\nimport { getVersionedNativeModulesAsync } from './bundledNativeModules';\nimport { hasExpoCanaryAsync } from './resolvePackages';\nimport { getVersionsAsync, SDKVersion } from '../../../api/getVersions';\nimport { Log } from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\n\nconst debug = require('debug')(\n 'expo:doctor:dependencies:getVersionedPackages'\n) as typeof console.log;\n\nexport type DependencyList = Record<string, string>;\n\n/** Adds `react-dom`, `react`, and `react-native` to the list of known package versions (`relatedPackages`) */\nfunction normalizeSdkVersionObject(version?: SDKVersion): Record<string, string> {\n if (!version) {\n return {};\n }\n const { relatedPackages, facebookReactVersion, facebookReactNativeVersion, expoVersion } =\n version;\n\n const reactVersion = facebookReactVersion\n ? {\n react: facebookReactVersion,\n 'react-dom': facebookReactVersion,\n }\n : undefined;\n\n const expoVersionIfAvailable = expoVersion ? { expo: expoVersion } : undefined;\n\n return {\n ...relatedPackages,\n ...reactVersion,\n ...expoVersionIfAvailable,\n 'react-native': facebookReactNativeVersion,\n };\n}\n\n/** Get the known versions for a given SDK, combines all sources. */\nexport async function getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion,\n skipCache,\n}: {\n projectRoot: string;\n sdkVersion?: string;\n skipCache?: boolean;\n}) {\n const skipRemoteVersions = await hasExpoCanaryAsync(projectRoot);\n if (skipRemoteVersions) {\n Log.warn('Dependency validation might be unreliable when using canary SDK versions');\n }\n\n if (env.EXPO_NO_DEPENDENCY_VALIDATION) {\n debug('Dependency validation is disabled through EXPO_NO_DEPENDENCY_VALIDATION=1');\n return {};\n }\n\n const bundledNativeModules = sdkVersion\n ? await getVersionedNativeModulesAsync(projectRoot, sdkVersion, { skipRemoteVersions })\n : {};\n const versionsForSdk = !skipRemoteVersions\n ? await getRemoteVersionsForSdkAsync({ sdkVersion, skipCache })\n : {};\n return {\n ...bundledNativeModules,\n // Prefer the remote versions over the bundled versions, this enables us to push\n // emergency fixes that users can access without having to update the `expo` package.\n ...versionsForSdk,\n };\n}\n\n/** @returns a key/value list of known dependencies and their version (including range). */\nexport async function getRemoteVersionsForSdkAsync({\n sdkVersion,\n skipCache,\n}: { sdkVersion?: string; skipCache?: boolean } = {}): Promise<DependencyList> {\n if (env.EXPO_OFFLINE) {\n Log.warn('Dependency validation is unreliable in offline-mode');\n return {};\n }\n\n try {\n const { sdkVersions } = await getVersionsAsync({ skipCache });\n\n // We only want versioned dependencies so skip if they cannot be found.\n if (!sdkVersion || !(sdkVersion in sdkVersions)) {\n debug(\n `Skipping versioned dependencies because the SDK version is not found. (sdkVersion: ${sdkVersion}, available: ${Object.keys(\n sdkVersions\n ).join(', ')})`\n );\n return {};\n }\n\n const version = sdkVersions[sdkVersion as keyof typeof sdkVersions] as unknown as SDKVersion;\n\n return normalizeSdkVersionObject(version);\n } catch (error: any) {\n if (error instanceof CommandError && error.code === 'OFFLINE') {\n return getRemoteVersionsForSdkAsync({ sdkVersion, skipCache });\n }\n throw error;\n }\n}\n\ntype ExcludedNativeModules = {\n name: string;\n bundledNativeVersion: string;\n isExcludedFromValidation: boolean;\n specifiedVersion?: string; // e.g. 1.2.3, latest\n};\n\n/**\n * Versions a list of `packages` against a given `sdkVersion` based on local and remote versioning resources.\n *\n * @param projectRoot\n * @param param1\n * @returns\n */\nexport async function getVersionedPackagesAsync(\n projectRoot: string,\n {\n packages,\n sdkVersion,\n pkg,\n }: {\n /** List of npm packages to process. */\n packages: string[];\n /** Target SDK Version number to version the `packages` for. */\n sdkVersion: string;\n pkg: PackageJSONConfig;\n }\n): Promise<{\n packages: string[];\n messages: string[];\n excludedNativeModules: ExcludedNativeModules[];\n}> {\n const versionsForSdk = await getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion,\n skipCache: true,\n });\n\n let nativeModulesCount = 0;\n let othersCount = 0;\n const excludedNativeModules: ExcludedNativeModules[] = [];\n\n const versionedPackages = packages.map((arg) => {\n const { name, type, raw, rawSpec } = npmPackageArg(arg);\n\n if (['tag', 'version', 'range'].includes(type) && name && versionsForSdk[name]) {\n // Unimodule packages from npm registry are modified to use the bundled version.\n // Some packages have the recommended version listed in https://exp.host/--/api/v2/versions.\n const isExcludedFromValidation = pkg?.expo?.install?.exclude?.includes(name);\n const hasSpecifiedExactVersion = rawSpec !== '' && rawSpec !== '*';\n if (isExcludedFromValidation || hasSpecifiedExactVersion) {\n othersCount++;\n excludedNativeModules.push({\n name,\n bundledNativeVersion: versionsForSdk[name],\n isExcludedFromValidation,\n specifiedVersion: hasSpecifiedExactVersion ? rawSpec : '',\n });\n return raw;\n }\n nativeModulesCount++;\n return `${name}@${versionsForSdk[name]}`;\n } else {\n // Other packages are passed through unmodified.\n othersCount++;\n return raw;\n }\n });\n\n const messages = getOperationLog({\n othersCount,\n nativeModulesCount,\n sdkVersion,\n });\n\n return {\n packages: versionedPackages,\n messages,\n excludedNativeModules,\n };\n}\n\n/** Craft a set of messages regarding the install operations. */\nexport function getOperationLog({\n nativeModulesCount,\n sdkVersion,\n othersCount,\n}: {\n nativeModulesCount: number;\n othersCount: number;\n sdkVersion: string;\n}): string[] {\n return [\n nativeModulesCount > 0 &&\n `${nativeModulesCount} SDK ${sdkVersion} compatible native ${\n nativeModulesCount === 1 ? 'module' : 'modules'\n }`,\n othersCount > 0 && `${othersCount} other ${othersCount === 1 ? 'package' : 'packages'}`,\n ].filter(Boolean) as string[];\n}\n"],"names":["getCombinedKnownVersionsAsync","getOperationLog","getRemoteVersionsForSdkAsync","getVersionedPackagesAsync","debug","require","normalizeSdkVersionObject","version","relatedPackages","facebookReactVersion","facebookReactNativeVersion","expoVersion","reactVersion","react","undefined","expoVersionIfAvailable","expo","projectRoot","sdkVersion","skipCache","skipRemoteVersions","hasExpoCanaryAsync","Log","warn","env","EXPO_NO_DEPENDENCY_VALIDATION","bundledNativeModules","getVersionedNativeModulesAsync","versionsForSdk","EXPO_OFFLINE","sdkVersions","getVersionsAsync","Object","keys","join","error","CommandError","code","packages","pkg","nativeModulesCount","othersCount","excludedNativeModules","versionedPackages","map","arg","name","type","raw","rawSpec","npmPackageArg","includes","isExcludedFromValidation","install","exclude","hasSpecifiedExactVersion","push","bundledNativeVersion","specifiedVersion","messages","filter","Boolean"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/doctor/dependencies/getVersionedPackages.ts"],"sourcesContent":["import { PackageJSONConfig } from '@expo/config';\nimport npmPackageArg from 'npm-package-arg';\n\nimport { getVersionedNativeModulesAsync } from './bundledNativeModules';\nimport { hasExpoCanaryAsync } from './resolvePackages';\nimport { getVersionsAsync, SDKVersion } from '../../../api/getVersions';\nimport { Log } from '../../../log';\nimport { env } from '../../../utils/env';\nimport { CommandError } from '../../../utils/errors';\n\nconst debug = require('debug')(\n 'expo:doctor:dependencies:getVersionedPackages'\n) as typeof console.log;\n\nexport type DependencyList = Record<string, string>;\n\n/** Adds `react-dom`, `react`, and `react-native` to the list of known package versions (`relatedPackages`) */\nfunction normalizeSdkVersionObject(version?: SDKVersion): Record<string, string> {\n if (!version) {\n return {};\n }\n const { relatedPackages, facebookReactVersion, facebookReactNativeVersion, expoVersion } =\n version;\n\n const reactVersion = facebookReactVersion\n ? {\n react: facebookReactVersion,\n 'react-dom': facebookReactVersion,\n }\n : undefined;\n\n const expoVersionIfAvailable = expoVersion ? { expo: expoVersion } : undefined;\n\n return {\n ...relatedPackages,\n ...reactVersion,\n ...expoVersionIfAvailable,\n 'react-native': facebookReactNativeVersion,\n };\n}\n\n/** Get the known versions for a given SDK, combines all sources. */\nexport async function getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion,\n skipCache,\n}: {\n projectRoot: string;\n sdkVersion?: string;\n skipCache?: boolean;\n}) {\n const skipRemoteVersions = await hasExpoCanaryAsync(projectRoot);\n if (skipRemoteVersions) {\n Log.warn('Dependency validation might be unreliable when using canary SDK versions');\n }\n\n const bundledNativeModules = sdkVersion\n ? await getVersionedNativeModulesAsync(projectRoot, sdkVersion, { skipRemoteVersions })\n : {};\n const versionsForSdk = !skipRemoteVersions\n ? await getRemoteVersionsForSdkAsync({ sdkVersion, skipCache })\n : {};\n return {\n ...bundledNativeModules,\n // Prefer the remote versions over the bundled versions, this enables us to push\n // emergency fixes that users can access without having to update the `expo` package.\n ...versionsForSdk,\n };\n}\n\n/** @returns a key/value list of known dependencies and their version (including range). */\nexport async function getRemoteVersionsForSdkAsync({\n sdkVersion,\n skipCache,\n}: { sdkVersion?: string; skipCache?: boolean } = {}): Promise<DependencyList> {\n if (env.EXPO_OFFLINE) {\n Log.warn('Dependency validation is unreliable in offline-mode');\n return {};\n }\n\n try {\n const { sdkVersions } = await getVersionsAsync({ skipCache });\n\n // We only want versioned dependencies so skip if they cannot be found.\n if (!sdkVersion || !(sdkVersion in sdkVersions)) {\n debug(\n `Skipping versioned dependencies because the SDK version is not found. (sdkVersion: ${sdkVersion}, available: ${Object.keys(\n sdkVersions\n ).join(', ')})`\n );\n return {};\n }\n\n const version = sdkVersions[sdkVersion as keyof typeof sdkVersions] as unknown as SDKVersion;\n\n return normalizeSdkVersionObject(version);\n } catch (error: any) {\n if (error instanceof CommandError && error.code === 'OFFLINE') {\n return getRemoteVersionsForSdkAsync({ sdkVersion, skipCache });\n }\n throw error;\n }\n}\n\ntype ExcludedNativeModules = {\n name: string;\n bundledNativeVersion: string;\n isExcludedFromValidation: boolean;\n specifiedVersion?: string; // e.g. 1.2.3, latest\n};\n\n/**\n * Versions a list of `packages` against a given `sdkVersion` based on local and remote versioning resources.\n *\n * @param projectRoot\n * @param param1\n * @returns\n */\nexport async function getVersionedPackagesAsync(\n projectRoot: string,\n {\n packages,\n sdkVersion,\n pkg,\n }: {\n /** List of npm packages to process. */\n packages: string[];\n /** Target SDK Version number to version the `packages` for. */\n sdkVersion: string;\n pkg: PackageJSONConfig;\n }\n): Promise<{\n packages: string[];\n messages: string[];\n excludedNativeModules: ExcludedNativeModules[];\n}> {\n const versionsForSdk = await getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion,\n skipCache: true,\n });\n\n let nativeModulesCount = 0;\n let othersCount = 0;\n const excludedNativeModules: ExcludedNativeModules[] = [];\n\n const versionedPackages = packages.map((arg) => {\n const { name, type, raw, rawSpec } = npmPackageArg(arg);\n\n if (['tag', 'version', 'range'].includes(type) && name && versionsForSdk[name]) {\n // Unimodule packages from npm registry are modified to use the bundled version.\n // Some packages have the recommended version listed in https://exp.host/--/api/v2/versions.\n const isExcludedFromValidation = pkg?.expo?.install?.exclude?.includes(name);\n const hasSpecifiedExactVersion = rawSpec !== '' && rawSpec !== '*';\n if (isExcludedFromValidation || hasSpecifiedExactVersion) {\n othersCount++;\n excludedNativeModules.push({\n name,\n bundledNativeVersion: versionsForSdk[name],\n isExcludedFromValidation,\n specifiedVersion: hasSpecifiedExactVersion ? rawSpec : '',\n });\n return raw;\n }\n nativeModulesCount++;\n return `${name}@${versionsForSdk[name]}`;\n } else {\n // Other packages are passed through unmodified.\n othersCount++;\n return raw;\n }\n });\n\n const messages = getOperationLog({\n othersCount,\n nativeModulesCount,\n sdkVersion,\n });\n\n return {\n packages: versionedPackages,\n messages,\n excludedNativeModules,\n };\n}\n\n/** Craft a set of messages regarding the install operations. */\nexport function getOperationLog({\n nativeModulesCount,\n sdkVersion,\n othersCount,\n}: {\n nativeModulesCount: number;\n othersCount: number;\n sdkVersion: string;\n}): string[] {\n return [\n nativeModulesCount > 0 &&\n `${nativeModulesCount} SDK ${sdkVersion} compatible native ${\n nativeModulesCount === 1 ? 'module' : 'modules'\n }`,\n othersCount > 0 && `${othersCount} other ${othersCount === 1 ? 'package' : 'packages'}`,\n ].filter(Boolean) as string[];\n}\n"],"names":["getCombinedKnownVersionsAsync","getOperationLog","getRemoteVersionsForSdkAsync","getVersionedPackagesAsync","debug","require","normalizeSdkVersionObject","version","relatedPackages","facebookReactVersion","facebookReactNativeVersion","expoVersion","reactVersion","react","undefined","expoVersionIfAvailable","expo","projectRoot","sdkVersion","skipCache","skipRemoteVersions","hasExpoCanaryAsync","Log","warn","bundledNativeModules","getVersionedNativeModulesAsync","versionsForSdk","env","EXPO_OFFLINE","sdkVersions","getVersionsAsync","Object","keys","join","error","CommandError","code","packages","pkg","nativeModulesCount","othersCount","excludedNativeModules","versionedPackages","map","arg","name","type","raw","rawSpec","npmPackageArg","includes","isExcludedFromValidation","install","exclude","hasSpecifiedExactVersion","push","bundledNativeVersion","specifiedVersion","messages","filter","Boolean"],"mappings":"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"}
@@ -112,6 +112,9 @@ async function validateDependenciesVersionsAsync(projectRoot, exp, pkg, packages
112
112
  if (_env.env.EXPO_OFFLINE) {
113
113
  _log.warn('Skipping dependency validation in offline mode');
114
114
  return null;
115
+ } else if (_env.env.EXPO_NO_DEPENDENCY_VALIDATION) {
116
+ debug('Dependency validation is disabled through EXPO_NO_DEPENDENCY_VALIDATION=1');
117
+ return null;
115
118
  }
116
119
  const incorrectDeps = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packagesToCheck);
117
120
  return logIncorrectDependencies(incorrectDeps);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/start/doctor/dependencies/validateDependenciesVersions.ts"],"sourcesContent":["import { ExpoConfig, PackageJSONConfig } from '@expo/config';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport npmPackageArg from 'npm-package-arg';\nimport semver from 'semver';\nimport semverRangeSubset from 'semver/ranges/subset';\n\nimport { BundledNativeModules } from './bundledNativeModules';\nimport { getCombinedKnownVersionsAsync } from './getVersionedPackages';\nimport { resolveAllPackageVersionsAsync } from './resolvePackages';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\n\nconst debug = require('debug')('expo:doctor:dependencies:validate') as typeof console.log;\n\ntype IncorrectDependency = {\n packageName: string;\n packageType: 'dependencies' | 'devDependencies';\n expectedVersionOrRange: string;\n actualVersion: string;\n};\n\ntype DependenciesToCheck = { known: string[]; unknown: string[] };\n\n/**\n * Print a list of incorrect dependency versions.\n * This only checks dependencies when not running in offline mode.\n *\n * @param projectRoot Expo project root.\n * @param exp Expo project config.\n * @param pkg Project's `package.json`.\n * @param packagesToCheck A list of packages to check, if undefined or empty, all will be checked.\n * @returns `true` if there are no incorrect dependencies.\n */\nexport async function validateDependenciesVersionsAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'sdkVersion'>,\n pkg: PackageJSONConfig,\n packagesToCheck?: string[]\n): Promise<boolean | null> {\n if (env.EXPO_OFFLINE) {\n Log.warn('Skipping dependency validation in offline mode');\n return null;\n }\n\n const incorrectDeps = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packagesToCheck);\n return logIncorrectDependencies(incorrectDeps);\n}\n\nfunction logInvalidDependency({\n packageName,\n expectedVersionOrRange,\n actualVersion,\n}: IncorrectDependency) {\n Log.warn(\n chalk` {bold ${packageName}}{cyan @}{red ${actualVersion}} - expected version: {green ${expectedVersionOrRange}}`\n );\n}\n\nexport function logIncorrectDependencies(incorrectDeps: IncorrectDependency[]) {\n if (!incorrectDeps.length) {\n return true;\n }\n\n Log.warn(\n chalk`The following packages should be updated for best compatibility with the installed {bold expo} version:`\n );\n incorrectDeps.forEach((dep) => logInvalidDependency(dep));\n\n Log.warn(\n 'Your project may not work correctly until you install the expected versions of the packages.'\n );\n\n return false;\n}\n\n/**\n * Return a list of versioned dependencies for the project SDK version.\n *\n * @param projectRoot Expo project root.\n * @param exp Expo project config.\n * @param pkg Project's `package.json`.\n * @param packagesToCheck A list of packages to check, if undefined or empty, all will be checked.\n * @returns A list of incorrect dependencies.\n */\nexport async function getVersionedDependenciesAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'sdkVersion'>,\n pkg: PackageJSONConfig,\n packagesToCheck?: string[]\n): Promise<IncorrectDependency[]> {\n // This should never happen under normal circumstances since\n // the CLI is versioned in the `expo` package.\n assert(exp.sdkVersion, 'SDK Version is missing');\n\n // Get from both endpoints and combine the known package versions.\n const combinedKnownPackages = await getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion: exp.sdkVersion,\n });\n // debug(`Known dependencies: %O`, combinedKnownPackages);\n\n const resolvedDependencies = packagesToCheck?.length\n ? // Diff the provided packages to ensure we only check against installed packages.\n getFilteredObject(packagesToCheck, { ...pkg.dependencies, ...pkg.devDependencies })\n : // If no packages are provided, check against the `package.json` `dependencies` + `devDependencies` object.\n { ...pkg.dependencies, ...pkg.devDependencies };\n debug(`Checking dependencies for ${exp.sdkVersion}: %O`, resolvedDependencies);\n\n // intersection of packages from package.json and bundled native modules\n const { known: resolvedPackagesToCheck, unknown } = getPackagesToCheck(\n combinedKnownPackages,\n resolvedDependencies\n );\n debug(`Comparing known versions: %O`, resolvedPackagesToCheck);\n debug(`Skipping packages that cannot be versioned automatically: %O`, unknown);\n // read package versions from the file system (node_modules)\n const packageVersions = await resolveAllPackageVersionsAsync(\n projectRoot,\n resolvedPackagesToCheck\n );\n debug(`Package versions: %O`, packageVersions);\n // find incorrect dependencies by comparing the actual package versions with the bundled native module version ranges\n let incorrectDeps = findIncorrectDependencies(pkg, packageVersions, combinedKnownPackages);\n debug(`Incorrect dependencies: %O`, incorrectDeps);\n\n if (pkg?.expo?.install?.exclude) {\n const packagesToExclude = pkg.expo.install.exclude;\n\n // Parse the exclude list to ensure we can factor in any specified version ranges\n const parsedPackagesToExclude = packagesToExclude.reduce(\n (acc: Record<string, npmPackageArg.Result>, packageName: string) => {\n const npaResult = npmPackageArg(packageName);\n if (typeof npaResult.name === 'string') {\n acc[npaResult.name] = npaResult;\n } else {\n acc[packageName] = npaResult;\n }\n return acc;\n },\n {}\n );\n\n const incorrectAndExcludedDeps = incorrectDeps\n .filter((dep) => {\n if (parsedPackagesToExclude[dep.packageName]) {\n const { name, raw, rawSpec, type } = parsedPackagesToExclude[dep.packageName];\n const suggestedRange = combinedKnownPackages[name];\n\n // If only the package name itself is specified, then we keep it in the exclude list\n if (name === raw) {\n return true;\n } else if (type === 'version') {\n return suggestedRange === rawSpec;\n } else if (type === 'range') {\n // Fall through exclusions if the suggested range is invalid\n if (!semver.validRange(suggestedRange)) {\n debug(\n `Invalid semver range in combined known packages for package ${name} in expo.install.exclude: %O`,\n suggestedRange\n );\n return false;\n }\n\n return semverRangeSubset(suggestedRange, rawSpec);\n } else {\n debug(\n `Unsupported npm package argument type for package ${name} in expo.install.exclude: %O`,\n type\n );\n }\n }\n\n return false;\n })\n .map((dep) => dep.packageName);\n\n debug(\n `Incorrect dependency warnings filtered out by expo.install.exclude: %O`,\n incorrectAndExcludedDeps\n );\n incorrectDeps = incorrectDeps.filter(\n (dep) => !incorrectAndExcludedDeps.includes(dep.packageName)\n );\n }\n\n return incorrectDeps;\n}\n\nfunction getFilteredObject(keys: string[], object: Record<string, string>) {\n return keys.reduce<Record<string, string>>((acc, key) => {\n acc[key] = object[key];\n return acc;\n }, {});\n}\n\nfunction getPackagesToCheck(\n bundledNativeModules: BundledNativeModules,\n dependencies?: Record<string, string> | null\n): DependenciesToCheck {\n const dependencyNames = Object.keys(dependencies ?? {});\n const known: string[] = [];\n const unknown: string[] = [];\n for (const dependencyName of dependencyNames) {\n if (dependencyName in bundledNativeModules) {\n known.push(dependencyName);\n } else {\n unknown.push(dependencyName);\n }\n }\n return { known, unknown };\n}\n\nfunction findIncorrectDependencies(\n pkg: PackageJSONConfig,\n packageVersions: Record<string, string>,\n bundledNativeModules: BundledNativeModules\n): IncorrectDependency[] {\n const packages = Object.keys(packageVersions);\n const incorrectDeps: IncorrectDependency[] = [];\n for (const packageName of packages) {\n const expectedVersionOrRange = bundledNativeModules[packageName];\n const actualVersion = packageVersions[packageName];\n if (isDependencyVersionIncorrect(packageName, actualVersion, expectedVersionOrRange)) {\n incorrectDeps.push({\n packageName,\n packageType: findDependencyType(pkg, packageName),\n expectedVersionOrRange,\n actualVersion,\n });\n }\n }\n return incorrectDeps;\n}\n\nexport function isDependencyVersionIncorrect(\n packageName: string,\n actualVersion: string,\n expectedVersionOrRange?: string\n) {\n if (!expectedVersionOrRange) {\n return false;\n }\n\n // we never want to go backwards with the expo patch version\n if (packageName === 'expo') {\n return semver.ltr(actualVersion, expectedVersionOrRange);\n }\n\n // For all other packages, check if the actual version satisfies the expected range\n const satisfies = semver.satisfies(actualVersion, expectedVersionOrRange, {\n includePrerelease: true,\n });\n\n return !satisfies;\n}\n\nfunction findDependencyType(\n pkg: PackageJSONConfig,\n packageName: string\n): IncorrectDependency['packageType'] {\n if (pkg.devDependencies && packageName in pkg.devDependencies) {\n return 'devDependencies';\n }\n\n return 'dependencies';\n}\n"],"names":["getVersionedDependenciesAsync","isDependencyVersionIncorrect","logIncorrectDependencies","validateDependenciesVersionsAsync","debug","require","projectRoot","exp","pkg","packagesToCheck","env","EXPO_OFFLINE","Log","warn","incorrectDeps","logInvalidDependency","packageName","expectedVersionOrRange","actualVersion","chalk","length","forEach","dep","assert","sdkVersion","combinedKnownPackages","getCombinedKnownVersionsAsync","resolvedDependencies","getFilteredObject","dependencies","devDependencies","known","resolvedPackagesToCheck","unknown","getPackagesToCheck","packageVersions","resolveAllPackageVersionsAsync","findIncorrectDependencies","expo","install","exclude","packagesToExclude","parsedPackagesToExclude","reduce","acc","npaResult","npmPackageArg","name","incorrectAndExcludedDeps","filter","raw","rawSpec","type","suggestedRange","semver","validRange","semverRangeSubset","map","includes","keys","object","key","bundledNativeModules","dependencyNames","Object","dependencyName","push","packages","packageType","findDependencyType","ltr","satisfies","includePrerelease"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../src/start/doctor/dependencies/validateDependenciesVersions.ts"],"sourcesContent":["import { ExpoConfig, PackageJSONConfig } from '@expo/config';\nimport assert from 'assert';\nimport chalk from 'chalk';\nimport npmPackageArg from 'npm-package-arg';\nimport semver from 'semver';\nimport semverRangeSubset from 'semver/ranges/subset';\n\nimport { BundledNativeModules } from './bundledNativeModules';\nimport { getCombinedKnownVersionsAsync } from './getVersionedPackages';\nimport { resolveAllPackageVersionsAsync } from './resolvePackages';\nimport * as Log from '../../../log';\nimport { env } from '../../../utils/env';\n\nconst debug = require('debug')('expo:doctor:dependencies:validate') as typeof console.log;\n\ntype IncorrectDependency = {\n packageName: string;\n packageType: 'dependencies' | 'devDependencies';\n expectedVersionOrRange: string;\n actualVersion: string;\n};\n\ntype DependenciesToCheck = { known: string[]; unknown: string[] };\n\n/**\n * Print a list of incorrect dependency versions.\n * This only checks dependencies when not running in offline mode.\n *\n * @param projectRoot Expo project root.\n * @param exp Expo project config.\n * @param pkg Project's `package.json`.\n * @param packagesToCheck A list of packages to check, if undefined or empty, all will be checked.\n * @returns `true` if there are no incorrect dependencies.\n */\nexport async function validateDependenciesVersionsAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'sdkVersion'>,\n pkg: PackageJSONConfig,\n packagesToCheck?: string[]\n): Promise<boolean | null> {\n if (env.EXPO_OFFLINE) {\n Log.warn('Skipping dependency validation in offline mode');\n return null;\n } else if (env.EXPO_NO_DEPENDENCY_VALIDATION) {\n debug('Dependency validation is disabled through EXPO_NO_DEPENDENCY_VALIDATION=1');\n return null;\n }\n\n const incorrectDeps = await getVersionedDependenciesAsync(projectRoot, exp, pkg, packagesToCheck);\n return logIncorrectDependencies(incorrectDeps);\n}\n\nfunction logInvalidDependency({\n packageName,\n expectedVersionOrRange,\n actualVersion,\n}: IncorrectDependency) {\n Log.warn(\n chalk` {bold ${packageName}}{cyan @}{red ${actualVersion}} - expected version: {green ${expectedVersionOrRange}}`\n );\n}\n\nexport function logIncorrectDependencies(incorrectDeps: IncorrectDependency[]) {\n if (!incorrectDeps.length) {\n return true;\n }\n\n Log.warn(\n chalk`The following packages should be updated for best compatibility with the installed {bold expo} version:`\n );\n incorrectDeps.forEach((dep) => logInvalidDependency(dep));\n\n Log.warn(\n 'Your project may not work correctly until you install the expected versions of the packages.'\n );\n\n return false;\n}\n\n/**\n * Return a list of versioned dependencies for the project SDK version.\n *\n * @param projectRoot Expo project root.\n * @param exp Expo project config.\n * @param pkg Project's `package.json`.\n * @param packagesToCheck A list of packages to check, if undefined or empty, all will be checked.\n * @returns A list of incorrect dependencies.\n */\nexport async function getVersionedDependenciesAsync(\n projectRoot: string,\n exp: Pick<ExpoConfig, 'sdkVersion'>,\n pkg: PackageJSONConfig,\n packagesToCheck?: string[]\n): Promise<IncorrectDependency[]> {\n // This should never happen under normal circumstances since\n // the CLI is versioned in the `expo` package.\n assert(exp.sdkVersion, 'SDK Version is missing');\n\n // Get from both endpoints and combine the known package versions.\n const combinedKnownPackages = await getCombinedKnownVersionsAsync({\n projectRoot,\n sdkVersion: exp.sdkVersion,\n });\n // debug(`Known dependencies: %O`, combinedKnownPackages);\n\n const resolvedDependencies = packagesToCheck?.length\n ? // Diff the provided packages to ensure we only check against installed packages.\n getFilteredObject(packagesToCheck, { ...pkg.dependencies, ...pkg.devDependencies })\n : // If no packages are provided, check against the `package.json` `dependencies` + `devDependencies` object.\n { ...pkg.dependencies, ...pkg.devDependencies };\n debug(`Checking dependencies for ${exp.sdkVersion}: %O`, resolvedDependencies);\n\n // intersection of packages from package.json and bundled native modules\n const { known: resolvedPackagesToCheck, unknown } = getPackagesToCheck(\n combinedKnownPackages,\n resolvedDependencies\n );\n debug(`Comparing known versions: %O`, resolvedPackagesToCheck);\n debug(`Skipping packages that cannot be versioned automatically: %O`, unknown);\n // read package versions from the file system (node_modules)\n const packageVersions = await resolveAllPackageVersionsAsync(\n projectRoot,\n resolvedPackagesToCheck\n );\n debug(`Package versions: %O`, packageVersions);\n // find incorrect dependencies by comparing the actual package versions with the bundled native module version ranges\n let incorrectDeps = findIncorrectDependencies(pkg, packageVersions, combinedKnownPackages);\n debug(`Incorrect dependencies: %O`, incorrectDeps);\n\n if (pkg?.expo?.install?.exclude) {\n const packagesToExclude = pkg.expo.install.exclude;\n\n // Parse the exclude list to ensure we can factor in any specified version ranges\n const parsedPackagesToExclude = packagesToExclude.reduce(\n (acc: Record<string, npmPackageArg.Result>, packageName: string) => {\n const npaResult = npmPackageArg(packageName);\n if (typeof npaResult.name === 'string') {\n acc[npaResult.name] = npaResult;\n } else {\n acc[packageName] = npaResult;\n }\n return acc;\n },\n {}\n );\n\n const incorrectAndExcludedDeps = incorrectDeps\n .filter((dep) => {\n if (parsedPackagesToExclude[dep.packageName]) {\n const { name, raw, rawSpec, type } = parsedPackagesToExclude[dep.packageName];\n const suggestedRange = combinedKnownPackages[name];\n\n // If only the package name itself is specified, then we keep it in the exclude list\n if (name === raw) {\n return true;\n } else if (type === 'version') {\n return suggestedRange === rawSpec;\n } else if (type === 'range') {\n // Fall through exclusions if the suggested range is invalid\n if (!semver.validRange(suggestedRange)) {\n debug(\n `Invalid semver range in combined known packages for package ${name} in expo.install.exclude: %O`,\n suggestedRange\n );\n return false;\n }\n\n return semverRangeSubset(suggestedRange, rawSpec);\n } else {\n debug(\n `Unsupported npm package argument type for package ${name} in expo.install.exclude: %O`,\n type\n );\n }\n }\n\n return false;\n })\n .map((dep) => dep.packageName);\n\n debug(\n `Incorrect dependency warnings filtered out by expo.install.exclude: %O`,\n incorrectAndExcludedDeps\n );\n incorrectDeps = incorrectDeps.filter(\n (dep) => !incorrectAndExcludedDeps.includes(dep.packageName)\n );\n }\n\n return incorrectDeps;\n}\n\nfunction getFilteredObject(keys: string[], object: Record<string, string>) {\n return keys.reduce<Record<string, string>>((acc, key) => {\n acc[key] = object[key];\n return acc;\n }, {});\n}\n\nfunction getPackagesToCheck(\n bundledNativeModules: BundledNativeModules,\n dependencies?: Record<string, string> | null\n): DependenciesToCheck {\n const dependencyNames = Object.keys(dependencies ?? {});\n const known: string[] = [];\n const unknown: string[] = [];\n for (const dependencyName of dependencyNames) {\n if (dependencyName in bundledNativeModules) {\n known.push(dependencyName);\n } else {\n unknown.push(dependencyName);\n }\n }\n return { known, unknown };\n}\n\nfunction findIncorrectDependencies(\n pkg: PackageJSONConfig,\n packageVersions: Record<string, string>,\n bundledNativeModules: BundledNativeModules\n): IncorrectDependency[] {\n const packages = Object.keys(packageVersions);\n const incorrectDeps: IncorrectDependency[] = [];\n for (const packageName of packages) {\n const expectedVersionOrRange = bundledNativeModules[packageName];\n const actualVersion = packageVersions[packageName];\n if (isDependencyVersionIncorrect(packageName, actualVersion, expectedVersionOrRange)) {\n incorrectDeps.push({\n packageName,\n packageType: findDependencyType(pkg, packageName),\n expectedVersionOrRange,\n actualVersion,\n });\n }\n }\n return incorrectDeps;\n}\n\nexport function isDependencyVersionIncorrect(\n packageName: string,\n actualVersion: string,\n expectedVersionOrRange?: string\n) {\n if (!expectedVersionOrRange) {\n return false;\n }\n\n // we never want to go backwards with the expo patch version\n if (packageName === 'expo') {\n return semver.ltr(actualVersion, expectedVersionOrRange);\n }\n\n // For all other packages, check if the actual version satisfies the expected range\n const satisfies = semver.satisfies(actualVersion, expectedVersionOrRange, {\n includePrerelease: true,\n });\n\n return !satisfies;\n}\n\nfunction findDependencyType(\n pkg: PackageJSONConfig,\n packageName: string\n): IncorrectDependency['packageType'] {\n if (pkg.devDependencies && packageName in pkg.devDependencies) {\n return 'devDependencies';\n }\n\n return 'dependencies';\n}\n"],"names":["getVersionedDependenciesAsync","isDependencyVersionIncorrect","logIncorrectDependencies","validateDependenciesVersionsAsync","debug","require","projectRoot","exp","pkg","packagesToCheck","env","EXPO_OFFLINE","Log","warn","EXPO_NO_DEPENDENCY_VALIDATION","incorrectDeps","logInvalidDependency","packageName","expectedVersionOrRange","actualVersion","chalk","length","forEach","dep","assert","sdkVersion","combinedKnownPackages","getCombinedKnownVersionsAsync","resolvedDependencies","getFilteredObject","dependencies","devDependencies","known","resolvedPackagesToCheck","unknown","getPackagesToCheck","packageVersions","resolveAllPackageVersionsAsync","findIncorrectDependencies","expo","install","exclude","packagesToExclude","parsedPackagesToExclude","reduce","acc","npaResult","npmPackageArg","name","incorrectAndExcludedDeps","filter","raw","rawSpec","type","suggestedRange","semver","validRange","semverRangeSubset","map","includes","keys","object","key","bundledNativeModules","dependencyNames","Object","dependencyName","push","packages","packageType","findDependencyType","ltr","satisfies","includePrerelease"],"mappings":"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"}
@@ -0,0 +1,173 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "cliExtensionMenuItemHandler", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return cliExtensionMenuItemHandler;
9
+ }
10
+ });
11
+ function _chalk() {
12
+ const data = /*#__PURE__*/ _interop_require_default(require("chalk"));
13
+ _chalk = function() {
14
+ return data;
15
+ };
16
+ return data;
17
+ }
18
+ const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../log"));
19
+ const _link = require("../../utils/link");
20
+ const _ora = require("../../utils/ora");
21
+ const _prompts = require("../../utils/prompts");
22
+ function _interop_require_default(obj) {
23
+ return obj && obj.__esModule ? obj : {
24
+ default: obj
25
+ };
26
+ }
27
+ function _getRequireWildcardCache(nodeInterop) {
28
+ if (typeof WeakMap !== "function") return null;
29
+ var cacheBabelInterop = new WeakMap();
30
+ var cacheNodeInterop = new WeakMap();
31
+ return (_getRequireWildcardCache = function(nodeInterop) {
32
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
33
+ })(nodeInterop);
34
+ }
35
+ function _interop_require_wildcard(obj, nodeInterop) {
36
+ if (!nodeInterop && obj && obj.__esModule) {
37
+ return obj;
38
+ }
39
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
40
+ return {
41
+ default: obj
42
+ };
43
+ }
44
+ var cache = _getRequireWildcardCache(nodeInterop);
45
+ if (cache && cache.has(obj)) {
46
+ return cache.get(obj);
47
+ }
48
+ var newObj = {
49
+ __proto__: null
50
+ };
51
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
52
+ for(var key in obj){
53
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
54
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
55
+ if (desc && (desc.get || desc.set)) {
56
+ Object.defineProperty(newObj, key, desc);
57
+ } else {
58
+ newObj[key] = obj[key];
59
+ }
60
+ }
61
+ }
62
+ newObj.default = obj;
63
+ if (cache) {
64
+ cache.set(obj, newObj);
65
+ }
66
+ return newObj;
67
+ }
68
+ const cliExtensionMenuItemHandler = async (plugin, command, metroServerOrigin)=>{
69
+ const cliExtensionsConfig = plugin.cliExtensions;
70
+ if (cliExtensionsConfig == null) {
71
+ return;
72
+ }
73
+ if (plugin.executor == null) {
74
+ _log.warn((0, _chalk().default)`{bold ${plugin.packageName}} does not support CLI commands.`);
75
+ return;
76
+ }
77
+ let args = {};
78
+ if (command.parameters && command.parameters.length > 0) {
79
+ args = await command.parameters.reduce(async (accPromise, param)=>{
80
+ const acc = await accPromise;
81
+ const result = await (0, _prompts.promptAsync)({
82
+ name: param.name,
83
+ type: param.type,
84
+ message: `${param.name}${param.description ? (0, _chalk().default)` {dim ${param.description}}` : ''}` + (0, _chalk().default)` {dim (${param.type})}`
85
+ });
86
+ if (result[param.name] == null) {
87
+ throw new Error('Input cancelled');
88
+ }
89
+ return {
90
+ ...acc,
91
+ [param.name]: result[param.name]
92
+ };
93
+ }, Promise.resolve({}));
94
+ }
95
+ // Confirm execution
96
+ const { value } = await (0, _prompts.promptAsync)({
97
+ message: (0, _chalk().default)`{dim Execute command "${command.title}":} "${plugin.executor.getCommandString({
98
+ command: command.name,
99
+ args
100
+ })}"`,
101
+ initial: false,
102
+ name: 'value',
103
+ type: 'confirm'
104
+ });
105
+ if (!value) {
106
+ return;
107
+ }
108
+ const spinnerText = `Executing command '${command.title}'`;
109
+ const spinner = (0, _ora.ora)(spinnerText).start();
110
+ try {
111
+ // Execute and stream the output
112
+ const results = await plugin.executor.execute({
113
+ command: command.name,
114
+ metroServerOrigin,
115
+ args,
116
+ onOutput: (output)=>handleOutput(output, spinner)
117
+ });
118
+ // Format with warning or success depending on wether the client reported any errors
119
+ formatResults(command.title, results, spinner);
120
+ } catch (error) {
121
+ spinner.fail(`Failed to execute command "${command.title}".\n${error.toString().trim()}`);
122
+ }
123
+ };
124
+ //*************************** Helpers ****************************/
125
+ function normalizeText(text, level) {
126
+ const trimText = text.trim();
127
+ if (level === 'error') {
128
+ return _chalk().default.red(trimText);
129
+ } else if (level === 'warning') {
130
+ return _chalk().default.yellow(trimText);
131
+ } else {
132
+ return trimText;
133
+ }
134
+ }
135
+ function appendSpinnerText(text, spinner) {
136
+ return spinner.text += '\n ' + text;
137
+ }
138
+ function handleOutput(output, spinner) {
139
+ output.forEach((line)=>{
140
+ switch(line.type){
141
+ case 'text':
142
+ appendSpinnerText(line.url ? (0, _link.link)(line.url, {
143
+ text: normalizeText(line.text, line.level),
144
+ dim: false
145
+ }) : normalizeText(line.text, line.level), spinner);
146
+ break;
147
+ case 'audio':
148
+ appendSpinnerText((0, _link.link)(line.url, {
149
+ text: line.text ?? 'Audio',
150
+ dim: false
151
+ }), spinner);
152
+ break;
153
+ case 'image':
154
+ appendSpinnerText((0, _link.link)(line.url, {
155
+ text: line.text ?? 'Image',
156
+ dim: false
157
+ }), spinner);
158
+ break;
159
+ }
160
+ });
161
+ }
162
+ function formatResults(command, results, spinner) {
163
+ const output = spinner.text.split('\n').slice(1).join('\n');
164
+ if (results.find((line)=>line.type === 'text' && line.level === 'error')) {
165
+ spinner.fail(`Command "${command}" completed with errors.\n${output}`);
166
+ } else if (results.find((line)=>line.type === 'text' && line.level === 'warning')) {
167
+ spinner.warn(`Command "${command}" completed with warnings.\n${output}`);
168
+ } else {
169
+ spinner.succeed(`Command "${command}" completed successfully.\n${output}`).stop();
170
+ }
171
+ }
172
+
173
+ //# sourceMappingURL=cliExtensionMenuItemHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/start/interface/cliExtensionMenuItemHandler.ts"],"sourcesContent":["import chalk from 'chalk';\nimport { Ora } from 'ora';\n\nimport * as Log from '../../log';\nimport { link } from '../../utils/link';\nimport { ora } from '../../utils/ora';\nimport { promptAsync } from '../../utils/prompts';\nimport { DevToolsPlugin } from '../server/DevToolsPlugin';\nimport { DevToolsPluginCommand, DevToolsPluginOutput } from '../server/DevToolsPlugin.schema';\n\n/**\n * Handles the CLI extension menu item selection and execution of the plugin command for use\n * in the cli context, logging to the terminal.\n *\n * The function will prompt for any required parameters, confirm execution, and display\n * output from the command execution.\n *\n * @param plugin The DevTools plugin.\n * @param command The command to execute.\n * @param metroServerOrigin The Metro server origin.\n * @returns\n */\nexport const cliExtensionMenuItemHandler = async (\n plugin: DevToolsPlugin,\n command: DevToolsPluginCommand,\n metroServerOrigin: string\n) => {\n const cliExtensionsConfig = plugin.cliExtensions;\n if (cliExtensionsConfig == null) {\n return;\n }\n\n if (plugin.executor == null) {\n Log.warn(chalk`{bold ${plugin.packageName}} does not support CLI commands.`);\n return;\n }\n\n let args: Record<string, string> = {};\n if (command.parameters && command.parameters.length > 0) {\n args = await command.parameters.reduce(\n async (accPromise, param) => {\n const acc = await accPromise;\n const result = await promptAsync({\n name: param.name,\n type: param.type,\n message:\n `${param.name}${param.description ? chalk` {dim ${param.description}}` : ''}` +\n chalk` {dim (${param.type})}`,\n });\n if (result[param.name] == null) {\n throw new Error('Input cancelled');\n }\n return { ...acc, [param.name]: result[param.name] };\n },\n Promise.resolve({} as Record<string, string>)\n );\n }\n\n // Confirm execution\n const { value } = await promptAsync({\n message: chalk`{dim Execute command \"${command.title}\":} \"${plugin.executor.getCommandString({ command: command.name, args })}\"`,\n initial: false,\n name: 'value',\n type: 'confirm',\n });\n\n if (!value) {\n return;\n }\n\n const spinnerText = `Executing command '${command.title}'`;\n const spinner = ora(spinnerText).start();\n\n try {\n // Execute and stream the output\n const results = await plugin.executor.execute({\n command: command.name,\n metroServerOrigin,\n args,\n onOutput: (output) => handleOutput(output, spinner),\n });\n\n // Format with warning or success depending on wether the client reported any errors\n formatResults(command.title, results, spinner);\n } catch (error: any) {\n spinner.fail(`Failed to execute command \"${command.title}\".\\n${error.toString().trim()}`);\n }\n};\n\n//*************************** Helpers ****************************/\n\nfunction normalizeText(text: string, level: 'info' | 'warning' | 'error') {\n const trimText = text.trim();\n if (level === 'error') {\n return chalk.red(trimText);\n } else if (level === 'warning') {\n return chalk.yellow(trimText);\n } else {\n return trimText;\n }\n}\n\nfunction appendSpinnerText(text: string, spinner: Ora) {\n return (spinner.text += '\\n ' + text);\n}\n\nfunction handleOutput(output: DevToolsPluginOutput, spinner: Ora) {\n output.forEach((line) => {\n switch (line.type) {\n case 'text':\n appendSpinnerText(\n line.url\n ? link(line.url, { text: normalizeText(line.text, line.level), dim: false })\n : normalizeText(line.text, line.level),\n spinner\n );\n break;\n case 'audio':\n appendSpinnerText(link(line.url, { text: line.text ?? 'Audio', dim: false }), spinner);\n break;\n case 'image':\n appendSpinnerText(link(line.url, { text: line.text ?? 'Image', dim: false }), spinner);\n break;\n }\n });\n}\n\nfunction formatResults(command: string, results: DevToolsPluginOutput, spinner: Ora) {\n const output = spinner.text.split('\\n').slice(1).join('\\n');\n if (results.find((line) => line.type === 'text' && line.level === 'error')) {\n spinner.fail(`Command \"${command}\" completed with errors.\\n${output}`);\n } else if (results.find((line) => line.type === 'text' && line.level === 'warning')) {\n spinner.warn(`Command \"${command}\" completed with warnings.\\n${output}`);\n } else {\n spinner.succeed(`Command \"${command}\" completed successfully.\\n${output}`).stop();\n }\n}\n"],"names":["cliExtensionMenuItemHandler","plugin","command","metroServerOrigin","cliExtensionsConfig","cliExtensions","executor","Log","warn","chalk","packageName","args","parameters","length","reduce","accPromise","param","acc","result","promptAsync","name","type","message","description","Error","Promise","resolve","value","title","getCommandString","initial","spinnerText","spinner","ora","start","results","execute","onOutput","output","handleOutput","formatResults","error","fail","toString","trim","normalizeText","text","level","trimText","red","yellow","appendSpinnerText","forEach","line","url","link","dim","split","slice","join","find","succeed","stop"],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ Object.defineProperty(exports, "createDevToolsMenuItems", {
6
+ enumerable: true,
7
+ get: function() {
8
+ return createDevToolsMenuItems;
9
+ }
10
+ });
11
+ function _chalk() {
12
+ const data = /*#__PURE__*/ _interop_require_default(require("chalk"));
13
+ _chalk = function() {
14
+ return data;
15
+ };
16
+ return data;
17
+ }
18
+ const _cliExtensionMenuItemHandler = require("./cliExtensionMenuItemHandler");
19
+ const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../log"));
20
+ const _open = require("../../utils/open");
21
+ const _prompts = require("../../utils/prompts");
22
+ function _interop_require_default(obj) {
23
+ return obj && obj.__esModule ? obj : {
24
+ default: obj
25
+ };
26
+ }
27
+ function _getRequireWildcardCache(nodeInterop) {
28
+ if (typeof WeakMap !== "function") return null;
29
+ var cacheBabelInterop = new WeakMap();
30
+ var cacheNodeInterop = new WeakMap();
31
+ return (_getRequireWildcardCache = function(nodeInterop) {
32
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
33
+ })(nodeInterop);
34
+ }
35
+ function _interop_require_wildcard(obj, nodeInterop) {
36
+ if (!nodeInterop && obj && obj.__esModule) {
37
+ return obj;
38
+ }
39
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
40
+ return {
41
+ default: obj
42
+ };
43
+ }
44
+ var cache = _getRequireWildcardCache(nodeInterop);
45
+ if (cache && cache.has(obj)) {
46
+ return cache.get(obj);
47
+ }
48
+ var newObj = {
49
+ __proto__: null
50
+ };
51
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
52
+ for(var key in obj){
53
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
54
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
55
+ if (desc && (desc.get || desc.set)) {
56
+ Object.defineProperty(newObj, key, desc);
57
+ } else {
58
+ newObj[key] = obj[key];
59
+ }
60
+ }
61
+ }
62
+ newObj.default = obj;
63
+ if (cache) {
64
+ cache.set(obj, newObj);
65
+ }
66
+ return newObj;
67
+ }
68
+ const debug = require('debug')('expo:start:devtools');
69
+ const createDevToolsMenuItems = (plugins, defaultServerUrl, metroServerOrigin, cliExtensionMenuItemHandlerFunc = _cliExtensionMenuItemHandler.cliExtensionMenuItemHandler, openBrowserAsyncFunc = _open // Used for injection when testing
70
+ .openBrowserAsync)=>{
71
+ return plugins.map((plugin)=>{
72
+ const commands = getCliExtensionCommands(plugin);
73
+ if (commands.length > 0 && plugin.webpageEndpoint) {
74
+ // Custom display/handling for plugins that support both web and CLI commands
75
+ const children = [
76
+ devtoolFactory(plugin, defaultServerUrl, openBrowserAsyncFunc),
77
+ ...commands.map((descriptor)=>({
78
+ title: descriptor.title,
79
+ value: descriptor.name,
80
+ action: async ()=>await cliExtensionMenuItemHandlerFunc(plugin, descriptor, metroServerOrigin)
81
+ }))
82
+ ].filter((item)=>item != null);
83
+ return {
84
+ title: (0, _chalk().default)`{bold ${plugin.packageName}}`,
85
+ value: '',
86
+ children,
87
+ action: async ()=>{
88
+ try {
89
+ var _children_find_action, _children_find;
90
+ const value = await (0, _prompts.selectAsync)((0, _chalk().default)`{dim Select command}`, children);
91
+ await ((_children_find = children.find((item)=>item.value === value)) == null ? void 0 : (_children_find_action = _children_find.action) == null ? void 0 : _children_find_action.call(_children_find));
92
+ } catch (error) {
93
+ // Handle aborting prompt
94
+ debug(`Aborted selection prompt by user: ${error.toString()}`);
95
+ }
96
+ }
97
+ };
98
+ } else if (plugin.webpageEndpoint) {
99
+ return devtoolFactory(plugin, defaultServerUrl);
100
+ } else if (plugin.cliExtensions && commands.length > 0) {
101
+ return cliExtensionFactory(plugin, metroServerOrigin);
102
+ }
103
+ return null;
104
+ }).filter((menuItem)=>menuItem != null);
105
+ };
106
+ const devtoolFactory = (plugin, defaultServerUrl, openBrowserAsyncFunc = _open // Used for injection when testing
107
+ .openBrowserAsync)=>{
108
+ if (plugin.webpageEndpoint == null) {
109
+ return null;
110
+ }
111
+ return {
112
+ title: (0, _chalk().default)`Open {bold ${plugin.packageName}}`,
113
+ value: `devtoolsPlugin:${plugin.packageName}`,
114
+ action: async ()=>{
115
+ const url = new URL(plugin.webpageEndpoint, defaultServerUrl);
116
+ await openBrowserAsyncFunc(url.toString());
117
+ }
118
+ };
119
+ };
120
+ const getCliExtensionCommands = (plugin)=>{
121
+ const cliExtensionsConfig = plugin.cliExtensions;
122
+ const commands = ((cliExtensionsConfig == null ? void 0 : cliExtensionsConfig.commands) ?? []).filter((p)=>{
123
+ var _p_environments;
124
+ return (_p_environments = p.environments) == null ? void 0 : _p_environments.includes('cli');
125
+ });
126
+ if (cliExtensionsConfig == null || commands.length === 0) {
127
+ return [];
128
+ }
129
+ return commands;
130
+ };
131
+ const cliExtensionFactory = (plugin, metroServerOrigin, cliExtensionMenuItemHandlerFunc = _cliExtensionMenuItemHandler // Used for injection when testing
132
+ .cliExtensionMenuItemHandler)=>{
133
+ const commands = getCliExtensionCommands(plugin);
134
+ const children = commands.map((cmd)=>({
135
+ title: cmd.title,
136
+ value: cmd.name
137
+ }));
138
+ return {
139
+ title: (0, _chalk().default)`{bold ${plugin.packageName}}`,
140
+ value: `cliExtension:${plugin.packageName}`,
141
+ children,
142
+ action: async ()=>{
143
+ try {
144
+ const value = await (0, _prompts.selectAsync)((0, _chalk().default)`{dim Select command}`, children);
145
+ const cmd = commands.find((c)=>c.name === value);
146
+ if (cmd == null) {
147
+ _log.warn(`No command found for ${plugin.packageName}`);
148
+ } else {
149
+ await cliExtensionMenuItemHandlerFunc(plugin, cmd, metroServerOrigin);
150
+ }
151
+ } catch (error) {
152
+ // Handle aborting prompt
153
+ debug(`Failed to execute command: ${error.toString()}`);
154
+ }
155
+ }
156
+ };
157
+ };
158
+
159
+ //# sourceMappingURL=createDevToolsMenuItems.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/start/interface/createDevToolsMenuItems.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport { cliExtensionMenuItemHandler } from './cliExtensionMenuItemHandler';\nimport * as Log from '../../log';\nimport { openBrowserAsync } from '../../utils/open';\nimport { ExpoChoice, selectAsync } from '../../utils/prompts';\nimport { DevToolsPlugin } from '../server/DevToolsPlugin';\nimport { DevToolsPluginCommand } from '../server/DevToolsPlugin.schema';\n\nconst debug = require('debug')('expo:start:devtools') as typeof console.log;\n\nexport interface MoreToolMenuItem extends ExpoChoice<string> {\n action?: () => unknown;\n}\n\ntype MenuItemWithSubmenu = MoreToolMenuItem & {\n children?: MenuItemWithSubmenu[];\n};\n\ntype CliExtensionMenuItemHandler = (\n plugin: DevToolsPlugin,\n cmd: DevToolsPluginCommand,\n metroServerOrigin: string\n) => Promise<void>;\n\n/**\n * Creates the menu items for the DevTools interface.\n * @param plugins The list of DevTools plugins.\n * @param defaultServerUrl The default server URL.\n * @param metroServerOrigin The Metro server origin.\n * @param cliExtensionMenuItemHandlerFunc The function to handle CLI extension menu items.\n * @param openBrowserAsyncFunc The function to open the browser.\n * @returns The menu items for the DevTools interface.\n */\nexport const createDevToolsMenuItems = (\n plugins: DevToolsPlugin[],\n defaultServerUrl: string,\n metroServerOrigin: string,\n cliExtensionMenuItemHandlerFunc: CliExtensionMenuItemHandler = cliExtensionMenuItemHandler, // Used for injection when testing\n openBrowserAsyncFunc: typeof openBrowserAsync = openBrowserAsync // Used for injection when testing\n): MenuItemWithSubmenu[] => {\n return plugins\n .map((plugin) => {\n const commands = getCliExtensionCommands(plugin);\n if (commands.length > 0 && plugin.webpageEndpoint) {\n // Custom display/handling for plugins that support both web and CLI commands\n const children = [\n devtoolFactory(plugin, defaultServerUrl, openBrowserAsyncFunc),\n ...commands.map((descriptor) => ({\n title: descriptor.title,\n value: descriptor.name,\n action: async () =>\n await cliExtensionMenuItemHandlerFunc(plugin, descriptor, metroServerOrigin),\n })),\n ].filter((item) => item != null);\n return {\n title: chalk`{bold ${plugin.packageName}}`,\n value: '',\n children,\n action: async () => {\n try {\n const value = await selectAsync(chalk`{dim Select command}`, children);\n await children.find((item) => item.value === value)?.action?.();\n } catch (error: any) {\n // Handle aborting prompt\n debug(`Aborted selection prompt by user: ${error.toString()}`);\n }\n },\n };\n } else if (plugin.webpageEndpoint) {\n return devtoolFactory(plugin, defaultServerUrl);\n } else if (plugin.cliExtensions && commands.length > 0) {\n return cliExtensionFactory(plugin, metroServerOrigin);\n }\n return null;\n })\n .filter((menuItem) => menuItem != null);\n};\n\nconst devtoolFactory = (\n plugin: DevToolsPlugin,\n defaultServerUrl: string,\n openBrowserAsyncFunc: typeof openBrowserAsync = openBrowserAsync // Used for injection when testing\n): MoreToolMenuItem | null => {\n if (plugin.webpageEndpoint == null) {\n return null;\n }\n\n return {\n title: chalk`Open {bold ${plugin.packageName}}`,\n value: `devtoolsPlugin:${plugin.packageName}`,\n action: async () => {\n const url = new URL(plugin.webpageEndpoint!, defaultServerUrl);\n await openBrowserAsyncFunc(url.toString());\n },\n };\n};\n\nconst getCliExtensionCommands = (plugin: DevToolsPlugin): DevToolsPluginCommand[] => {\n const cliExtensionsConfig = plugin.cliExtensions;\n const commands = (cliExtensionsConfig?.commands ?? []).filter((p) =>\n p.environments?.includes('cli')\n );\n\n if (cliExtensionsConfig == null || commands.length === 0) {\n return [];\n }\n return commands;\n};\n\nconst cliExtensionFactory = (\n plugin: DevToolsPlugin,\n metroServerOrigin: string,\n cliExtensionMenuItemHandlerFunc: CliExtensionMenuItemHandler = cliExtensionMenuItemHandler // Used for injection when testing\n): MenuItemWithSubmenu | null => {\n const commands = getCliExtensionCommands(plugin);\n const children = commands.map((cmd) => ({\n title: cmd.title,\n value: cmd.name,\n }));\n\n return {\n title: chalk`{bold ${plugin.packageName}}`,\n value: `cliExtension:${plugin.packageName}`,\n children,\n action: async () => {\n try {\n const value = await selectAsync(chalk`{dim Select command}`, children);\n const cmd = commands.find((c) => c.name === value);\n if (cmd == null) {\n Log.warn(`No command found for ${plugin.packageName}`);\n } else {\n await cliExtensionMenuItemHandlerFunc(plugin, cmd, metroServerOrigin);\n }\n } catch (error: any) {\n // Handle aborting prompt\n debug(`Failed to execute command: ${error.toString()}`);\n }\n },\n };\n};\n"],"names":["createDevToolsMenuItems","debug","require","plugins","defaultServerUrl","metroServerOrigin","cliExtensionMenuItemHandlerFunc","cliExtensionMenuItemHandler","openBrowserAsyncFunc","openBrowserAsync","map","plugin","commands","getCliExtensionCommands","length","webpageEndpoint","children","devtoolFactory","descriptor","title","value","name","action","filter","item","chalk","packageName","selectAsync","find","error","toString","cliExtensions","cliExtensionFactory","menuItem","url","URL","cliExtensionsConfig","p","environments","includes","cmd","c","Log","warn"],"mappings":"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"}
@@ -16,10 +16,10 @@ function _chalk() {
16
16
  return data;
17
17
  }
18
18
  const _commandsTable = require("./commandsTable");
19
+ const _createDevToolsMenuItems = require("./createDevToolsMenuItems");
19
20
  const _log = /*#__PURE__*/ _interop_require_wildcard(require("../../log"));
20
21
  const _env = require("../../utils/env");
21
22
  const _link = require("../../utils/link");
22
- const _open = require("../../utils/open");
23
23
  const _prompts = require("../../utils/prompts");
24
24
  const _JsInspector = require("../server/middleware/inspector/JsInspector");
25
25
  function _interop_require_default(obj) {
@@ -174,19 +174,15 @@ class DevServerManagerActions {
174
174
  value: 'reload'
175
175
  }
176
176
  ];
177
- const pluginMenuItems = (await this.devServerManager.devtoolsPluginManager.queryPluginsAsync()).map((plugin)=>({
178
- title: (0, _chalk().default)`Open {bold ${plugin.packageName}}`,
179
- value: `devtoolsPlugin:${plugin.packageName}`,
180
- action: async ()=>{
181
- const url = new URL(plugin.webpageEndpoint, this.devServerManager.getDefaultDevServer().getUrlCreator().constructUrl({
182
- scheme: 'http'
183
- }));
184
- await (0, _open.openBrowserAsync)(url.toString());
185
- }
186
- }));
177
+ const defaultServerUrl = this.devServerManager.getDefaultDevServer().getUrlCreator().constructUrl({
178
+ scheme: 'http'
179
+ });
180
+ const metroServerOrigin = this.devServerManager.getDefaultDevServer().getJsInspectorBaseUrl();
181
+ const plugins = await this.devServerManager.devtoolsPluginManager.queryPluginsAsync();
182
+ _log.log();
187
183
  const menuItems = [
188
184
  ...defaultMenuItems,
189
- ...pluginMenuItems
185
+ ...(0, _createDevToolsMenuItems.createDevToolsMenuItems)(plugins, defaultServerUrl, metroServerOrigin)
190
186
  ];
191
187
  const value = await (0, _prompts.selectAsync)((0, _chalk().default)`Dev tools {dim (native only)}`, menuItems);
192
188
  const menuItem = menuItems.find((item)=>item.value === value);