1import { createRunOncePlugin, Mod, withDangerousMod } from '@expo/config-plugins';
2import { ExpoConfig } from '@expo/config-types';
3// @ts-expect-error missing types
4import withDevLauncher from 'expo-dev-launcher/app.plugin';
5// @ts-expect-error missing types
6import withDevMenu from 'expo-dev-menu/app.plugin';
7import fs from 'fs';
8import path from 'path';
9
10import { InstallationPage } from './constants';
11import { withGeneratedAndroidScheme } from './withGeneratedAndroidScheme';
12import { withGeneratedIosScheme } from './withGeneratedIosScheme';
13
14const pkg = require('expo-dev-client/package.json');
15
16const REACT_NATIVE_CONFIG_JS = `// File created by expo-dev-client/app.plugin.js
17
18module.exports = {
19  dependencies: {
20    ...require('expo-dev-client/dependencies'),
21  },
22};
23`;
24
25function withReactNativeConfigJs(config: ExpoConfig): ExpoConfig {
26  config = withDangerousMod(config, ['android', addReactNativeConfigAsync]);
27  config = withDangerousMod(config, ['ios', addReactNativeConfigAsync]);
28  return config;
29}
30
31const addReactNativeConfigAsync: Mod = async (config) => {
32  const filename = path.join(config.modRequest.projectRoot, 'react-native.config.js');
33  try {
34    const config = fs.readFileSync(filename, 'utf8');
35    if (!config.includes('expo-dev-client/dependencies')) {
36      throw new Error(
37        `Could not add expo-dev-client dependencies to existing file ${filename}. See expo-dev-client installation instructions to add them manually: ${InstallationPage}`
38      );
39    }
40  } catch (error: any) {
41    if (error.code === 'ENOENT') {
42      // The file doesn't exist, so we create it.
43      fs.writeFileSync(filename, REACT_NATIVE_CONFIG_JS);
44    } else {
45      throw error;
46    }
47  }
48  return config;
49};
50
51function withDevClient(config: ExpoConfig) {
52  config = withDevMenu(config);
53  config = withDevLauncher(config);
54  config = withReactNativeConfigJs(config);
55  config = withGeneratedAndroidScheme(config);
56  config = withGeneratedIosScheme(config);
57  return config;
58}
59
60export default createRunOncePlugin(withDevClient, pkg.name, pkg.version);
61