1"use strict";
2var __importDefault = (this && this.__importDefault) || function (mod) {
3    return (mod && mod.__esModule) ? mod : { "default": mod };
4};
5Object.defineProperty(exports, "__esModule", { value: true });
6const config_plugins_1 = require("@expo/config-plugins");
7const fs_1 = __importDefault(require("fs"));
8const path_1 = __importDefault(require("path"));
9const semver_1 = __importDefault(require("semver"));
10const constants_1 = require("./constants");
11const resolveExpoUpdatesVersion_1 = require("./resolveExpoUpdatesVersion");
12const withDevLauncherAppDelegate_1 = require("./withDevLauncherAppDelegate");
13const pkg = require('expo-dev-launcher/package.json');
14const DEV_LAUNCHER_ANDROID_IMPORT = 'expo.modules.devlauncher.DevLauncherController';
15const DEV_LAUNCHER_UPDATES_ANDROID_IMPORT = 'expo.modules.updates.UpdatesDevLauncherController';
16const DEV_LAUNCHER_ON_NEW_INTENT = `
17  @Override
18  public void onNewIntent(Intent intent) {
19      if (DevLauncherController.tryToHandleIntent(this, intent)) {
20         return;
21      }
22      super.onNewIntent(intent);
23  }
24`;
25const DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE = `DevLauncherController.wrapReactActivityDelegate(this, () -> $1);`;
26const DEV_LAUNCHER_ANDROID_INIT = 'DevLauncherController.initialize(this, getReactNativeHost());';
27const DEV_LAUNCHER_UPDATES_ANDROID_INIT = `if (BuildConfig.DEBUG) {
28      DevLauncherController.getInstance().setUpdatesInterface(UpdatesDevLauncherController.initialize(this));
29    }`;
30const DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT = 'return DevLauncherController.getInstance().getUseDeveloperSupport();';
31const DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS = `import 'expo-dev-client'`;
32const DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS_VIA_LAUNCHER = `import 'expo-dev-launcher'`;
33async function readFileAsync(path) {
34    return fs_1.default.promises.readFile(path, 'utf8');
35}
36async function saveFileAsync(path, content) {
37    return fs_1.default.promises.writeFile(path, content, 'utf8');
38}
39function addLines(content, find, offset, toAdd) {
40    const lines = content.split('\n');
41    let lineIndex = lines.findIndex((line) => line.match(find));
42    for (const newLine of toAdd) {
43        if (!content.includes(newLine)) {
44            lines.splice(lineIndex + offset, 0, newLine);
45            lineIndex++;
46        }
47    }
48    return lines.join('\n');
49}
50function replaceLine(content, find, replace) {
51    const lines = content.split('\n');
52    if (!content.includes(replace)) {
53        const lineIndex = lines.findIndex((line) => line.match(find));
54        lines.splice(lineIndex, 1, replace);
55    }
56    return lines.join('\n');
57}
58function addJavaImports(javaSource, javaImports) {
59    const lines = javaSource.split('\n');
60    const lineIndexWithPackageDeclaration = lines.findIndex((line) => line.match(/^package .*;$/));
61    for (const javaImport of javaImports) {
62        if (!javaSource.includes(javaImport)) {
63            const importStatement = `import ${javaImport};`;
64            lines.splice(lineIndexWithPackageDeclaration + 1, 0, importStatement);
65        }
66    }
67    return lines.join('\n');
68}
69async function editMainApplication(config, action) {
70    const mainApplicationPath = path_1.default.join(config.modRequest.platformProjectRoot, 'app', 'src', 'main', 'java', ...config.android.package.split('.'), 'MainApplication.java');
71    try {
72        const mainApplication = action(await readFileAsync(mainApplicationPath));
73        return await saveFileAsync(mainApplicationPath, mainApplication);
74    }
75    catch (e) {
76        config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Couldn't modify MainApplication.java - ${e}.
77See the expo-dev-client installation instructions to modify your MainApplication.java manually: ${constants_1.InstallationPage}`);
78    }
79}
80async function editPodfile(config, action) {
81    const podfilePath = path_1.default.join(config.modRequest.platformProjectRoot, 'Podfile');
82    try {
83        const podfile = action(await readFileAsync(podfilePath));
84        return await saveFileAsync(podfilePath, podfile);
85    }
86    catch (e) {
87        config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify AppDelegate.m - ${e}.
88See the expo-dev-client installation instructions to modify your AppDelegate.m manually: ${constants_1.InstallationPage}`);
89    }
90}
91async function editIndex(config, action) {
92    const indexPath = path_1.default.join(config.modRequest.projectRoot, 'index.js');
93    try {
94        const index = action(await readFileAsync(indexPath));
95        return await saveFileAsync(indexPath, index);
96    }
97    catch (e) {
98        config_plugins_1.WarningAggregator.addWarningIOS('expo-dev-launcher', `Couldn't modify index.js - ${e}.
99See the expo-dev-client installation instructions to modify your index.js manually: ${constants_1.InstallationPage}`);
100    }
101}
102const withDevLauncherApplication = (config) => {
103    return config_plugins_1.withDangerousMod(config, [
104        'android',
105        async (config) => {
106            await editMainApplication(config, (mainApplication) => {
107                mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_ANDROID_IMPORT]);
108                mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
109                    `    ${DEV_LAUNCHER_ANDROID_INIT}`,
110                ]);
111                let expoUpdatesVersion;
112                try {
113                    expoUpdatesVersion = resolveExpoUpdatesVersion_1.resolveExpoUpdatesVersion(config.modRequest.projectRoot);
114                }
115                catch (e) {
116                    config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Failed to check compatibility with expo-updates - ${e}`);
117                }
118                if (expoUpdatesVersion && semver_1.default.gt(expoUpdatesVersion, '0.6.0')) {
119                    mainApplication = addJavaImports(mainApplication, [DEV_LAUNCHER_UPDATES_ANDROID_IMPORT]);
120                    mainApplication = addLines(mainApplication, 'initializeFlipper\\(this', 0, [
121                        `    ${DEV_LAUNCHER_UPDATES_ANDROID_INIT}`,
122                    ]);
123                    mainApplication = replaceLine(mainApplication, 'return BuildConfig.DEBUG;', `      ${DEV_LAUNCHER_UPDATES_DEVELOPER_SUPPORT}`);
124                }
125                return mainApplication;
126            });
127            return config;
128        },
129    ]);
130};
131const withDevLauncherActivity = (config) => {
132    return config_plugins_1.withMainActivity(config, (config) => {
133        if (config.modResults.language === 'java') {
134            let content = addJavaImports(config.modResults.contents, [
135                DEV_LAUNCHER_ANDROID_IMPORT,
136                'android.content.Intent',
137            ]);
138            if (!content.includes(DEV_LAUNCHER_ON_NEW_INTENT)) {
139                const lines = content.split('\n');
140                const onCreateIndex = lines.findIndex((line) => line.includes('public class MainActivity'));
141                lines.splice(onCreateIndex + 1, 0, DEV_LAUNCHER_ON_NEW_INTENT);
142                content = lines.join('\n');
143            }
144            if (!content.includes('DevLauncherController.wrapReactActivityDelegate')) {
145                content = content.replace(/(new ReactActivityDelegate(.*|\s)*});$/m, DEV_LAUNCHER_WRAPPED_ACTIVITY_DELEGATE);
146            }
147            config.modResults.contents = content;
148        }
149        else {
150            config_plugins_1.WarningAggregator.addWarningAndroid('expo-dev-launcher', `Cannot automatically configure MainActivity if it's not java.
151See the expo-dev-client installation instructions to modify your MainActivity manually: ${constants_1.InstallationPage}`);
152        }
153        return config;
154    });
155};
156const withDevLauncherPodfile = (config) => {
157    return config_plugins_1.withDangerousMod(config, [
158        'ios',
159        async (config) => {
160            await editPodfile(config, (podfile) => {
161                podfile = podfile.replace("platform :ios, '10.0'", "platform :ios, '11.0'");
162                // Match both variations of Ruby config:
163                // unknown: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', :configurations => :debug
164                // Rubocop: pod 'expo-dev-launcher', path: '../node_modules/expo-dev-launcher', configurations: :debug
165                if (!podfile.match(/pod ['"]expo-dev-launcher['"],\s?path: ['"][^'"]*node_modules\/expo-dev-launcher['"],\s?:?configurations:?\s(?:=>\s)?:debug/)) {
166                    const packagePath = path_1.default.dirname(require.resolve('expo-dev-launcher/package.json'));
167                    const relativePath = path_1.default.relative(config.modRequest.platformProjectRoot, packagePath);
168                    podfile = addLines(podfile, 'use_react_native', 0, [
169                        `  pod 'expo-dev-launcher', path: '${relativePath}', :configurations => :debug`,
170                    ]);
171                }
172                return podfile;
173            });
174            return config;
175        },
176    ]);
177};
178const withErrorHandling = (config) => {
179    const injectErrorHandlers = async (config) => {
180        await editIndex(config, (index) => {
181            if (!index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS) &&
182                !index.includes(DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS_VIA_LAUNCHER)) {
183                index = DEV_LAUNCHER_JS_REGISTER_ERROR_HANDLERS + ';\n\n' + index;
184            }
185            return index;
186        });
187        return config;
188    };
189    // We need to run the same task twice to ensure it will work on both platforms,
190    // because if someone runs `expo run:ios`, it will trigger only dangerous mode for that specific platform.
191    // Note: after the first execution, the second one won't change anything.
192    config = config_plugins_1.withDangerousMod(config, ['android', injectErrorHandlers]);
193    config = config_plugins_1.withDangerousMod(config, ['ios', injectErrorHandlers]);
194    return config;
195};
196const withDevLauncher = (config) => {
197    config = withDevLauncherActivity(config);
198    config = withDevLauncherApplication(config);
199    config = withDevLauncherPodfile(config);
200    config = withDevLauncherAppDelegate_1.withDevLauncherAppDelegate(config);
201    config = withErrorHandling(config);
202    return config;
203};
204exports.default = config_plugins_1.createRunOncePlugin(withDevLauncher, pkg.name, pkg.version);
205