Repository: expo/expo
File: packages/expo-build-properties/src/pluginConfig.ts (TypeScript)

Code before:
const fixupDeprecatedEnableProguardInReleaseBuilds = (config: unknown) => {
  if (
    config &&
    typeof config === 'object' &&
    'android' in config &&
    config.android &&
    typeof config.android === 'object'
  ) {
    const androidConfig = config.android as PluginConfigTypeAndroid & Record<string, unknown>;
    if (androidConfig.enableProguardInReleaseBuilds != null) {
      if (androidConfig.enableMinifyInReleaseBuilds === undefined) {
        androidConfig.enableMinifyInReleaseBuilds = !!androidConfig.enableProguardInReleaseBuilds;
      }
    }
  }
};

/**
 * Reads the hermes-compiler version from node_modules
 * @ignore
 */
function getHermesCompilerVersion(projectRoot: string): string | null {
  const hermesCompilerPackageJsonPath = resolveFrom.silent(
    resolveFrom.silent(projectRoot, 'react-native/package.json') ?? projectRoot,
    'hermes-compiler/package.json'
  );
  if (!hermesCompilerPackageJsonPath || !fs.existsSync(hermesCompilerPackageJsonPath)) {
    return null;
  }

  try {
    const packageJson = JSON.parse(fs.readFileSync(hermesCompilerPackageJsonPath, 'utf8'));
    return packageJson.version ?? null;
  } catch {
    return null;
  }
}

/**
 * @ignore
 */
export function validateConfig(config: unknown, projectRoot?: string): PluginConfigType {
  fixupDeprecatedEnableProguardInReleaseBuilds(config);
  validate(schema, config);
  maybeThrowInvalidVersions(config);

  if (
    config.android?.enableShrinkResourcesInReleaseBuilds === true &&
    config.android?.enableMinifyInReleaseBuilds !== true
  ) {
    throw new Error(

Review comment (bug):
```suggestion
  const reactNativePath = resolveFrom.silent(projectRoot, 'react-native/package.json');
  const hermesCompilerPackageJsonPath = reactNativePath && resolveFrom.silent(reactNativePath, 'hermes-compiler/package.json');
```

The fallback to `?? projectRoot` is probably something we want to avoid. While this is a workaround, since the resolution is presumably necessary, if `react-native` is not installed (and we don't alternatively have a peer dependency, which fwiw, most Expo modules should have in the future), then falling back to `projectRoot` is dangerous, since it could pick the wrong version of `hermes-compiler`, assuming that `react-native`'s builds should/will always pick their dependency on it

Code after:
const fixupDeprecatedEnableProguardInReleaseBuilds = (config: unknown) => {
  if (
    config &&
    typeof config === 'object' &&
    'android' in config &&
    config.android &&
    typeof config.android === 'object'
  ) {
    const androidConfig = config.android as PluginConfigTypeAndroid & Record<string, unknown>;
    if (androidConfig.enableProguardInReleaseBuilds != null) {
      if (androidConfig.enableMinifyInReleaseBuilds === undefined) {
        androidConfig.enableMinifyInReleaseBuilds = !!androidConfig.enableProguardInReleaseBuilds;
      }
    }
  }
};

/**
 * Reads the hermes-compiler version from node_modules
 * @ignore
 */
function getHermesCompilerVersion(projectRoot: string): string | null {
  const reactNativePath = resolveFrom.silent(projectRoot, 'react-native/package.json');
  const hermesCompilerPackageJsonPath =
    reactNativePath && resolveFrom.silent(reactNativePath, 'hermes-compiler/package.json');
  if (!hermesCompilerPackageJsonPath) {
    return null;
  }

  try {
    const packageJson = JSON.parse(fs.readFileSync(hermesCompilerPackageJsonPath, 'utf8'));
    return packageJson.version ?? null;
  } catch {
    return null;
  }
}

/**
 * @ignore
 */
export function validateConfig(config: unknown, projectRoot?: string): PluginConfigType {
  fixupDeprecatedEnableProguardInReleaseBuilds(config);
  validate(schema, config);
  maybeThrowInvalidVersions(config);

  if (
    config.android?.enableShrinkResourcesInReleaseBuilds === true &&
    config.android?.enableMinifyInReleaseBuilds !== true
  ) {
    throw new Error(
      '`android.enableShrinkResourcesInReleaseBuilds` requires `android.enableMinifyInReleaseBuilds` to be enabled.'