1082815dcSEvan Bacon"use strict"; 2082815dcSEvan Bacon 3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", { 4082815dcSEvan Bacon value: true 5082815dcSEvan Bacon}); 6082815dcSEvan Baconexports.getApplicationIdAsync = getApplicationIdAsync; 7082815dcSEvan Baconexports.getPackage = getPackage; 8082815dcSEvan Baconexports.renameJniOnDiskForType = renameJniOnDiskForType; 9082815dcSEvan Baconexports.renamePackageOnDisk = renamePackageOnDisk; 10082815dcSEvan Baconexports.renamePackageOnDiskForType = renamePackageOnDiskForType; 11082815dcSEvan Baconexports.setPackageInBuildGradle = setPackageInBuildGradle; 123216ce43SKudo Chienexports.withPackageRefactor = exports.withPackageGradle = void 0; 13082815dcSEvan Baconfunction _debug() { 14082815dcSEvan Bacon const data = _interopRequireDefault(require("debug")); 15082815dcSEvan Bacon _debug = function () { 16082815dcSEvan Bacon return data; 17082815dcSEvan Bacon }; 18082815dcSEvan Bacon return data; 19082815dcSEvan Bacon} 20082815dcSEvan Baconfunction _fs() { 21082815dcSEvan Bacon const data = _interopRequireDefault(require("fs")); 22082815dcSEvan Bacon _fs = function () { 23082815dcSEvan Bacon return data; 24082815dcSEvan Bacon }; 25082815dcSEvan Bacon return data; 26082815dcSEvan Bacon} 27082815dcSEvan Baconfunction _glob() { 28082815dcSEvan Bacon const data = require("glob"); 29082815dcSEvan Bacon _glob = function () { 30082815dcSEvan Bacon return data; 31082815dcSEvan Bacon }; 32082815dcSEvan Bacon return data; 33082815dcSEvan Bacon} 34082815dcSEvan Baconfunction _path() { 35082815dcSEvan Bacon const data = _interopRequireDefault(require("path")); 36082815dcSEvan Bacon _path = function () { 37082815dcSEvan Bacon return data; 38082815dcSEvan Bacon }; 39082815dcSEvan Bacon return data; 40082815dcSEvan Bacon} 41*8a424bebSJames Idefunction _Paths() { 42*8a424bebSJames Ide const data = require("./Paths"); 43*8a424bebSJames Ide _Paths = function () { 44*8a424bebSJames Ide return data; 45*8a424bebSJames Ide }; 46*8a424bebSJames Ide return data; 47*8a424bebSJames Ide} 48082815dcSEvan Baconfunction _androidPlugins() { 49082815dcSEvan Bacon const data = require("../plugins/android-plugins"); 50082815dcSEvan Bacon _androidPlugins = function () { 51082815dcSEvan Bacon return data; 52082815dcSEvan Bacon }; 53082815dcSEvan Bacon return data; 54082815dcSEvan Bacon} 55082815dcSEvan Baconfunction _withDangerousMod() { 56082815dcSEvan Bacon const data = require("../plugins/withDangerousMod"); 57082815dcSEvan Bacon _withDangerousMod = function () { 58082815dcSEvan Bacon return data; 59082815dcSEvan Bacon }; 60082815dcSEvan Bacon return data; 61082815dcSEvan Bacon} 62082815dcSEvan Baconfunction _modules() { 63082815dcSEvan Bacon const data = require("../utils/modules"); 64082815dcSEvan Bacon _modules = function () { 65082815dcSEvan Bacon return data; 66082815dcSEvan Bacon }; 67082815dcSEvan Bacon return data; 68082815dcSEvan Bacon} 69082815dcSEvan Baconfunction _warnings() { 70082815dcSEvan Bacon const data = require("../utils/warnings"); 71082815dcSEvan Bacon _warnings = function () { 72082815dcSEvan Bacon return data; 73082815dcSEvan Bacon }; 74082815dcSEvan Bacon return data; 75082815dcSEvan Bacon} 76082815dcSEvan Baconfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 77082815dcSEvan Baconconst debug = (0, _debug().default)('expo:config-plugins:android:package'); 78082815dcSEvan Baconconst withPackageGradle = config => { 79082815dcSEvan Bacon return (0, _androidPlugins().withAppBuildGradle)(config, config => { 80082815dcSEvan Bacon if (config.modResults.language === 'groovy') { 81082815dcSEvan Bacon config.modResults.contents = setPackageInBuildGradle(config, config.modResults.contents); 82082815dcSEvan Bacon } else { 83082815dcSEvan Bacon (0, _warnings().addWarningAndroid)('android.package', `Cannot automatically configure app build.gradle if it's not groovy`); 84082815dcSEvan Bacon } 85082815dcSEvan Bacon return config; 86082815dcSEvan Bacon }); 87082815dcSEvan Bacon}; 88082815dcSEvan Baconexports.withPackageGradle = withPackageGradle; 89082815dcSEvan Baconconst withPackageRefactor = config => { 90082815dcSEvan Bacon return (0, _withDangerousMod().withDangerousMod)(config, ['android', async config => { 91082815dcSEvan Bacon await renamePackageOnDisk(config, config.modRequest.projectRoot); 92082815dcSEvan Bacon return config; 93082815dcSEvan Bacon }]); 94082815dcSEvan Bacon}; 95082815dcSEvan Baconexports.withPackageRefactor = withPackageRefactor; 96082815dcSEvan Baconfunction getPackage(config) { 97082815dcSEvan Bacon var _config$android$packa, _config$android; 98082815dcSEvan Bacon return (_config$android$packa = (_config$android = config.android) === null || _config$android === void 0 ? void 0 : _config$android.package) !== null && _config$android$packa !== void 0 ? _config$android$packa : null; 99082815dcSEvan Bacon} 100082815dcSEvan Baconfunction getPackageRoot(projectRoot, type) { 101082815dcSEvan Bacon return _path().default.join(projectRoot, 'android', 'app', 'src', type, 'java'); 102082815dcSEvan Bacon} 103082815dcSEvan Baconfunction getCurrentPackageName(projectRoot, packageRoot) { 104082815dcSEvan Bacon const mainApplication = (0, _Paths().getProjectFilePath)(projectRoot, 'MainApplication'); 105082815dcSEvan Bacon const packagePath = _path().default.dirname(mainApplication); 106082815dcSEvan Bacon const packagePathParts = _path().default.relative(packageRoot, packagePath).split(_path().default.sep).filter(Boolean); 107082815dcSEvan Bacon return packagePathParts.join('.'); 108082815dcSEvan Bacon} 109082815dcSEvan Baconfunction getCurrentPackageForProjectFile(projectRoot, packageRoot, fileName, type) { 110082815dcSEvan Bacon const filePath = (0, _glob().sync)(_path().default.join(projectRoot, `android/app/src/${type}/java/**/${fileName}.@(java|kt)`))[0]; 111082815dcSEvan Bacon if (!filePath) { 112082815dcSEvan Bacon return null; 113082815dcSEvan Bacon } 114082815dcSEvan Bacon const packagePath = _path().default.dirname(filePath); 115082815dcSEvan Bacon const packagePathParts = _path().default.relative(packageRoot, packagePath).split(_path().default.sep).filter(Boolean); 116082815dcSEvan Bacon return packagePathParts.join('.'); 117082815dcSEvan Bacon} 118082815dcSEvan Baconfunction getCurrentPackageNameForType(projectRoot, type) { 119082815dcSEvan Bacon const packageRoot = getPackageRoot(projectRoot, type); 120082815dcSEvan Bacon if (type === 'main') { 121082815dcSEvan Bacon return getCurrentPackageName(projectRoot, packageRoot); 122ee216927STomasz Sapeta } 123ee216927STomasz Sapeta // debug, etc.. 124082815dcSEvan Bacon return getCurrentPackageForProjectFile(projectRoot, packageRoot, '*', type); 125ee216927STomasz Sapeta} 126ee216927STomasz Sapeta 127ee216927STomasz Sapeta// NOTE(brentvatne): this assumes that our MainApplication.java file is in the root of the package 128082815dcSEvan Bacon// this makes sense for standard react-native projects but may not apply in customized projects, so if 129082815dcSEvan Bacon// we want this to be runnable in any app we need to handle other possibilities 130082815dcSEvan Baconasync function renamePackageOnDisk(config, projectRoot) { 131082815dcSEvan Bacon const newPackageName = getPackage(config); 132082815dcSEvan Bacon if (newPackageName === null) { 133082815dcSEvan Bacon return; 134082815dcSEvan Bacon } 13584f418d7SKudo Chien for (const type of ['debug', 'main', 'release']) { 136082815dcSEvan Bacon await renameJniOnDiskForType({ 137082815dcSEvan Bacon projectRoot, 138082815dcSEvan Bacon type, 139082815dcSEvan Bacon packageName: newPackageName 140082815dcSEvan Bacon }); 141082815dcSEvan Bacon await renamePackageOnDiskForType({ 142082815dcSEvan Bacon projectRoot, 143082815dcSEvan Bacon type, 144082815dcSEvan Bacon packageName: newPackageName 145082815dcSEvan Bacon }); 146082815dcSEvan Bacon } 147082815dcSEvan Bacon} 148082815dcSEvan Baconasync function renameJniOnDiskForType({ 149082815dcSEvan Bacon projectRoot, 150082815dcSEvan Bacon type, 151082815dcSEvan Bacon packageName 152082815dcSEvan Bacon}) { 153082815dcSEvan Bacon if (!packageName) { 154082815dcSEvan Bacon return; 155082815dcSEvan Bacon } 156082815dcSEvan Bacon const currentPackageName = getCurrentPackageNameForType(projectRoot, type); 157082815dcSEvan Bacon if (!currentPackageName || !packageName || currentPackageName === packageName) { 158082815dcSEvan Bacon return; 159082815dcSEvan Bacon } 160082815dcSEvan Bacon const jniRoot = _path().default.join(projectRoot, 'android', 'app', 'src', type, 'jni'); 161082815dcSEvan Bacon const filesToUpdate = [...(0, _glob().sync)('**/*', { 162082815dcSEvan Bacon cwd: jniRoot, 163082815dcSEvan Bacon absolute: true 164ee216927STomasz Sapeta })]; 165ee216927STomasz Sapeta // Replace all occurrences of the path in the project 166082815dcSEvan Bacon filesToUpdate.forEach(filepath => { 167082815dcSEvan Bacon try { 168082815dcSEvan Bacon if (_fs().default.lstatSync(filepath).isFile() && ['.h', '.cpp'].includes(_path().default.extname(filepath))) { 169082815dcSEvan Bacon let contents = _fs().default.readFileSync(filepath).toString(); 170082815dcSEvan Bacon contents = contents.replace(new RegExp(transformJavaClassDescriptor(currentPackageName).replace(/\//g, '\\/'), 'g'), transformJavaClassDescriptor(packageName)); 171082815dcSEvan Bacon _fs().default.writeFileSync(filepath, contents); 172082815dcSEvan Bacon } 173082815dcSEvan Bacon } catch { 174082815dcSEvan Bacon debug(`Error updating "${filepath}" for type "${type}"`); 175082815dcSEvan Bacon } 176082815dcSEvan Bacon }); 177082815dcSEvan Bacon} 178082815dcSEvan Baconasync function renamePackageOnDiskForType({ 179082815dcSEvan Bacon projectRoot, 180082815dcSEvan Bacon type, 181082815dcSEvan Bacon packageName 182082815dcSEvan Bacon}) { 183082815dcSEvan Bacon if (!packageName) { 184082815dcSEvan Bacon return; 185082815dcSEvan Bacon } 186082815dcSEvan Bacon const currentPackageName = getCurrentPackageNameForType(projectRoot, type); 187082815dcSEvan Bacon debug(`Found package "${currentPackageName}" for type "${type}"`); 188082815dcSEvan Bacon if (!currentPackageName || currentPackageName === packageName) { 189082815dcSEvan Bacon return; 190082815dcSEvan Bacon } 191082815dcSEvan Bacon debug(`Refactor "${currentPackageName}" to "${packageName}" for type "${type}"`); 192ee216927STomasz Sapeta const packageRoot = getPackageRoot(projectRoot, type); 193ee216927STomasz Sapeta // Set up our paths 194082815dcSEvan Bacon if (!(await (0, _modules().directoryExistsAsync)(packageRoot))) { 195082815dcSEvan Bacon debug(`- skipping refactor of missing directory: ${packageRoot}`); 196082815dcSEvan Bacon return; 197082815dcSEvan Bacon } 198082815dcSEvan Bacon const currentPackagePath = _path().default.join(packageRoot, ...currentPackageName.split('.')); 199ee216927STomasz Sapeta const newPackagePath = _path().default.join(packageRoot, ...packageName.split('.')); 200082815dcSEvan Bacon 201ee216927STomasz Sapeta // Create the new directory 202082815dcSEvan Bacon _fs().default.mkdirSync(newPackagePath, { 203082815dcSEvan Bacon recursive: true 204ee216927STomasz Sapeta }); 205082815dcSEvan Bacon 206ee216927STomasz Sapeta // Move everything from the old directory over 207082815dcSEvan Bacon (0, _glob().sync)('**/*', { 208082815dcSEvan Bacon cwd: currentPackagePath 209082815dcSEvan Bacon }).forEach(relativePath => { 210082815dcSEvan Bacon const filepath = _path().default.join(currentPackagePath, relativePath); 211082815dcSEvan Bacon if (_fs().default.lstatSync(filepath).isFile()) { 212082815dcSEvan Bacon moveFileSync(filepath, _path().default.join(newPackagePath, relativePath)); 213082815dcSEvan Bacon } else { 214082815dcSEvan Bacon _fs().default.mkdirSync(filepath, { 215082815dcSEvan Bacon recursive: true 216082815dcSEvan Bacon }); 217082815dcSEvan Bacon } 218ee216927STomasz Sapeta }); 219ee216927STomasz Sapeta 220ee216927STomasz Sapeta // Remove the old directory recursively from com/old/package to com/old and com, 221082815dcSEvan Bacon // as long as the directories are empty 222082815dcSEvan Bacon const oldPathParts = currentPackageName.split('.'); 223082815dcSEvan Bacon while (oldPathParts.length) { 224082815dcSEvan Bacon const pathToCheck = _path().default.join(packageRoot, ...oldPathParts); 225082815dcSEvan Bacon try { 226082815dcSEvan Bacon const files = _fs().default.readdirSync(pathToCheck); 227082815dcSEvan Bacon if (files.length === 0) { 228082815dcSEvan Bacon _fs().default.rmdirSync(pathToCheck); 229082815dcSEvan Bacon } 230082815dcSEvan Bacon } finally { 231082815dcSEvan Bacon oldPathParts.pop(); 232082815dcSEvan Bacon } 233082815dcSEvan Bacon } 234082815dcSEvan Bacon const filesToUpdate = [...(0, _glob().sync)('**/*', { 235082815dcSEvan Bacon cwd: newPackagePath, 236082815dcSEvan Bacon absolute: true 237ee216927STomasz Sapeta })]; 238ee216927STomasz Sapeta // Only update the BUCK file to match the main package name 239082815dcSEvan Bacon if (type === 'main') { 240ed3bd27bSEvan Bacon // NOTE(EvanBacon): We dropped this file in SDK 48 but other templates may still use it. 241082815dcSEvan Bacon filesToUpdate.push(_path().default.join(projectRoot, 'android', 'app', 'BUCK')); 242ee216927STomasz Sapeta } 243ee216927STomasz Sapeta // Replace all occurrences of the path in the project 244082815dcSEvan Bacon filesToUpdate.forEach(filepath => { 245082815dcSEvan Bacon try { 246082815dcSEvan Bacon if (_fs().default.lstatSync(filepath).isFile()) { 247082815dcSEvan Bacon let contents = _fs().default.readFileSync(filepath).toString(); 248082815dcSEvan Bacon contents = contents.replace(new RegExp(currentPackageName, 'g'), packageName); 249082815dcSEvan Bacon if (['.h', '.cpp'].includes(_path().default.extname(filepath))) { 250082815dcSEvan Bacon contents = contents.replace(new RegExp(transformJavaClassDescriptor(currentPackageName).replace(/\//g, '\\'), 'g'), transformJavaClassDescriptor(packageName)); 251082815dcSEvan Bacon } 252082815dcSEvan Bacon _fs().default.writeFileSync(filepath, contents); 253082815dcSEvan Bacon } 254082815dcSEvan Bacon } catch { 255082815dcSEvan Bacon debug(`Error updating "${filepath}" for type "${type}"`); 256082815dcSEvan Bacon } 257082815dcSEvan Bacon }); 258082815dcSEvan Bacon} 259082815dcSEvan Baconfunction moveFileSync(src, dest) { 260082815dcSEvan Bacon _fs().default.mkdirSync(_path().default.dirname(dest), { 261082815dcSEvan Bacon recursive: true 262082815dcSEvan Bacon }); 263082815dcSEvan Bacon _fs().default.renameSync(src, dest); 264082815dcSEvan Bacon} 265082815dcSEvan Baconfunction setPackageInBuildGradle(config, buildGradle) { 266082815dcSEvan Bacon const packageName = getPackage(config); 267082815dcSEvan Bacon if (packageName === null) { 268082815dcSEvan Bacon return buildGradle; 269082815dcSEvan Bacon } 27084f418d7SKudo Chien const pattern = new RegExp(`(applicationId|namespace) ['"].*['"]`, 'g'); 27184f418d7SKudo Chien return buildGradle.replace(pattern, `$1 '${packageName}'`); 272082815dcSEvan Bacon} 273082815dcSEvan Baconasync function getApplicationIdAsync(projectRoot) { 274082815dcSEvan Bacon var _matchResult$; 275082815dcSEvan Bacon const buildGradlePath = (0, _Paths().getAppBuildGradleFilePath)(projectRoot); 276082815dcSEvan Bacon if (!_fs().default.existsSync(buildGradlePath)) { 277082815dcSEvan Bacon return null; 278082815dcSEvan Bacon } 279082815dcSEvan Bacon const buildGradle = await _fs().default.promises.readFile(buildGradlePath, 'utf8'); 280ee216927STomasz Sapeta const matchResult = buildGradle.match(/applicationId ['"](.*)['"]/); 281ee216927STomasz Sapeta // TODO add fallback for legacy cases to read from AndroidManifest.xml 282082815dcSEvan Bacon return (_matchResult$ = matchResult === null || matchResult === void 0 ? void 0 : matchResult[1]) !== null && _matchResult$ !== void 0 ? _matchResult$ : null; 283082815dcSEvan Bacon} 284ee216927STomasz Sapeta 285082815dcSEvan Bacon/** 286082815dcSEvan Bacon * Transform a java package name to java class descriptor, 287082815dcSEvan Bacon * e.g. `com.helloworld` -> `Lcom/helloworld`. 288082815dcSEvan Bacon */ 289082815dcSEvan Baconfunction transformJavaClassDescriptor(packageName) { 290082815dcSEvan Bacon return `L${packageName.replace(/\./g, '/')}`; 291082815dcSEvan Bacon} 292082815dcSEvan Bacon//# sourceMappingURL=Package.js.map