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