├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .npmignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── package.json └── src ├── config ├── bundleIdentifiers.js ├── filesToModifyContent.js └── foldersAndFiles.js └── index.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "prettier"], 3 | "parser": "babel-eslint", 4 | "plugins": ["prettier"], 5 | "parserOptions": { 6 | "ecmaVersion": 6, 7 | "sourceType": "module" 8 | }, 9 | "env": { 10 | "browser": true, 11 | "es6": true, 12 | "node": true 13 | }, 14 | "rules": { 15 | "arrow-body-style": [1, "as-needed"], 16 | "indent": ["off", "spaces", { "SwitchCase": 1, "VariableDeclarator": 1 }], 17 | "no-alert": 0, 18 | "no-console": 0, 19 | "no-debugger": 1, 20 | "newline-before-return": "error", 21 | "no-useless-escape": 0 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | lib 4 | .vscode 5 | yarn-error.log 6 | package-lock.json 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib 2 | package.json 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "singleQuote": true, 4 | "trailingComma": "es5" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 June Domingo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @strdr4605/react-native-rename 2 | 3 | Rename react-native app with just one command 4 | 5 | :warning::warning::warning: 6 | **NOTE:** This package is a fork of [react-native-rename@2.4.1](https://github.com/junedomingo/react-native-rename/tree/99aed0cf788d7e95c481e733de414cb2be76fa64) with several improvements. 7 | - [Validate bundleID to match requirements for Android](https://github.com/junedomingo/react-native-rename/pull/93) 8 | - [Change package name for other java files](https://github.com/junedomingo/react-native-rename/issues/95) 9 | 10 | :warning::warning::warning: Probable will be depricated in future if original package will implement these changes 11 | 12 | ![react-native-rename](https://cloud.githubusercontent.com/assets/5106887/24444940/cbcb0a58-149a-11e7-9714-2c7bf5254b0d.gif) 13 | 14 | > This package assumes that you created your react-native project using `react-native init`. 15 | 16 | **Note:** This package does not attempt to properly rename build artifacts such as `ios/build` or Cocoa Pod installation targets. After renaming your project you should clean, build, and reinstall third party dependencies to get it running properly with the new name. 17 | 18 | ## Installation 19 | ``` 20 | npm install @strdr4605/react-native-rename -g 21 | ``` 22 | 23 | Switch to new branch first 24 | > better to have back-up 25 | 26 | ``` 27 | git checkout -b rename-app 28 | ``` 29 | 30 | ## Usage 31 | ``` 32 | react-native-rename "" 33 | # or 34 | npx @strdr4605/react-native-rename "" 35 | ``` 36 | 37 | > With custom Bundle Identifier (Android only. For iOS, please use Xcode) 38 | ``` 39 | react-native-rename "" -b 40 | ``` 41 | 42 | ## Example 43 | ``` 44 | npx @strdr4605/react-native-rename "Travel App" 45 | ``` 46 | > With custom Bundle Identifier 47 | ``` 48 | npx @strdr4605/react-native-rename "Travel App" -b io.github.strdr4605.travelapp 49 | ``` 50 | 51 | 52 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@strdr4605/react-native-rename", 3 | "version": "2.5.0", 4 | "description": "Rename react-native app with just one command", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "prepublish": "babel src --out-dir lib", 9 | "relink": "sudo npm unlink && sudo npm run prepublish && sudo npm link", 10 | "format": "prettier --write '**/*.{js,jsx}'", 11 | "lint": "eslint '**/*.{js,jsx}'", 12 | "react-native-rename": "babel-node src/index.js", 13 | "precommit": "lint-staged" 14 | }, 15 | "files": [ 16 | "lib" 17 | ], 18 | "publishConfig": { 19 | "access": "public" 20 | }, 21 | "lint-staged": { 22 | "**/*.js": [ 23 | "format", 24 | "lint --fix", 25 | "git add" 26 | ] 27 | }, 28 | "repository": { 29 | "type": "git", 30 | "url": "git+https://github.com/strdr4605/react-native-rename.git" 31 | }, 32 | "keywords": [ 33 | "react-native", 34 | "ios", 35 | "android", 36 | "rename", 37 | "renamer", 38 | "react", 39 | "space" 40 | ], 41 | "author": "Dragoș Străinu ", 42 | "license": "MIT", 43 | "bin": { 44 | "react-native-rename": "lib/index.js" 45 | }, 46 | "bugs": { 47 | "url": "https://github.com/strdr4605/react-native-rename/issues" 48 | }, 49 | "homepage": "https://github.com/strdr4605/react-native-rename#readme", 50 | "dependencies": { 51 | "cheerio": "^0.22.0", 52 | "colors": "^1.1.2", 53 | "commander": "^2.9.0", 54 | "node-replace": "^0.3.3", 55 | "shelljs": "^0.7.7" 56 | }, 57 | "babel": { 58 | "presets": [ 59 | "es2015", 60 | "stage-2" 61 | ], 62 | "plugins": [ 63 | "transform-unicode-property-regex" 64 | ] 65 | }, 66 | "devDependencies": { 67 | "babel-cli": "^6.26.0", 68 | "babel-eslint": "^8.0.1", 69 | "babel-plugin-transform-unicode-property-regex": "^2.0.5", 70 | "babel-preset-es2015": "^6.24.1", 71 | "babel-preset-stage-2": "^6.13.0", 72 | "eslint": "^4.10.0", 73 | "eslint-config-prettier": "^2.7.0", 74 | "eslint-plugin-prettier": "^2.3.1", 75 | "eslint-watch": "^3.1.3", 76 | "husky": "^0.14.3", 77 | "lint-staged": "^4.3.0", 78 | "prettier": "^1.7.4" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/config/bundleIdentifiers.js: -------------------------------------------------------------------------------- 1 | // nS - No Space 2 | // lC - Lowercase 3 | 4 | export function bundleIdentifiers(currentAppName, newName, projectName, currentBundleID, newBundleID, newBundlePath) { 5 | const nS_CurrentAppName = currentAppName.replace(/\s/g, ''); 6 | const nS_NewName = newName.replace(/\s/g, ''); 7 | const lC_Ns_CurrentBundleID = currentBundleID.toLowerCase(); 8 | const lC_Ns_NewBundleID = newBundleID.toLowerCase(); 9 | 10 | return [ 11 | { 12 | regex: currentBundleID, 13 | replacement: newBundleID, 14 | paths: ['android/app/BUCK', 'android/app/build.gradle', 'android/app/src/main/AndroidManifest.xml'], 15 | }, 16 | { 17 | regex: currentBundleID, 18 | replacement: newBundleID, 19 | paths: [`${newBundlePath}/MainActivity.java`, `${newBundlePath}/MainApplication.java`], 20 | }, 21 | { 22 | regex: lC_Ns_CurrentBundleID, 23 | replacement: lC_Ns_NewBundleID, 24 | paths: [`${newBundlePath}/MainApplication.java`], 25 | }, 26 | { 27 | // App name (probably) doesn't start with `.`, but the bundle ID will 28 | // include the `.`. This fixes a possible issue where the bundle ID 29 | // also contains the app name and prevents it from being inappropriately 30 | // replaced by an update to the app name with the same bundle ID 31 | regex: new RegExp(`(?!\\.)(.|^)${nS_CurrentAppName}`, 'g'), 32 | replacement: `$1${nS_NewName}`, 33 | paths: [`${newBundlePath}/MainActivity.java`], 34 | }, 35 | ]; 36 | } 37 | -------------------------------------------------------------------------------- /src/config/filesToModifyContent.js: -------------------------------------------------------------------------------- 1 | // nS - No Space 2 | // lC - Lowercase 3 | 4 | export function filesToModifyContent(currentAppName, newName) { 5 | const nS_CurrentAppName = currentAppName.replace(/\s/g, ''); 6 | const nS_NewName = newName.replace(/\s/g, ''); 7 | 8 | return [ 9 | { 10 | regex: `${currentAppName}`, 11 | replacement: `${newName}`, 12 | paths: ['android/app/src/main/res/values/strings.xml'], 13 | }, 14 | { 15 | regex: nS_CurrentAppName, 16 | replacement: nS_NewName, 17 | paths: [ 18 | 'index.js', 19 | 'index.android.js', 20 | 'index.ios.js', 21 | `ios/${nS_NewName}.xcodeproj/project.pbxproj`, 22 | `ios/${nS_NewName}.xcworkspace/contents.xcworkspacedata`, 23 | `ios/${nS_NewName}.xcodeproj/xcshareddata/xcschemes/${nS_NewName}-tvOS.xcscheme`, 24 | `ios/${nS_NewName}.xcodeproj/xcshareddata/xcschemes/${nS_NewName}.xcscheme`, 25 | `ios/${nS_NewName}/AppDelegate.m`, 26 | 'android/settings.gradle', 27 | `ios/${nS_NewName}Tests/${nS_NewName}Tests.m`, 28 | 'ios/build/info.plist', 29 | 'ios/Podfile', 30 | 'app.json', 31 | ], 32 | }, 33 | { 34 | regex: `text="${currentAppName}"`, 35 | replacement: `text="${newName}"`, 36 | paths: [`ios/${nS_NewName}/Base.lproj/LaunchScreen.xib`], 37 | }, 38 | { 39 | regex: currentAppName, 40 | replacement: newName, 41 | paths: [`ios/${nS_NewName}/Info.plist`], 42 | }, 43 | { 44 | regex: `"name": "${nS_CurrentAppName}"`, 45 | replacement: `"name": "${nS_NewName}"`, 46 | paths: ['package.json'], 47 | }, 48 | { 49 | regex: `"displayName": "${currentAppName}"`, 50 | replacement: `"displayName": "${newName}"`, 51 | paths: ['app.json'], 52 | }, 53 | ]; 54 | } 55 | -------------------------------------------------------------------------------- /src/config/foldersAndFiles.js: -------------------------------------------------------------------------------- 1 | // nS - No Space 2 | // lC - Lowercase 3 | 4 | export function foldersAndFiles(currentAppName, newName) { 5 | const nS_CurrentAppName = currentAppName.replace(/\s/g, ''); 6 | const nS_NewName = newName.replace(/\s/g, ''); 7 | 8 | return [ 9 | `ios/${nS_CurrentAppName}`, 10 | `ios/${nS_CurrentAppName}-tvOS`, 11 | `ios/${nS_CurrentAppName}-tvOSTests`, 12 | `ios/${nS_CurrentAppName}.xcodeproj`, 13 | `ios/${nS_NewName}.xcodeproj/xcshareddata/xcschemes/${nS_CurrentAppName}-tvOS.xcscheme`, 14 | `ios/${nS_NewName}.xcodeproj/xcshareddata/xcschemes/${nS_CurrentAppName}.xcscheme`, 15 | `ios/${nS_CurrentAppName}Tests`, 16 | `ios/${nS_NewName}Tests/${nS_CurrentAppName}Tests.m`, 17 | `ios/${nS_CurrentAppName}.xcworkspace`, 18 | `ios/${nS_NewName}/${nS_CurrentAppName}.entitlements`, 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // nS - No Space 4 | // lC - Lowercase 5 | 6 | import cheerio from 'cheerio'; 7 | import colors from 'colors'; 8 | import fs from 'fs'; 9 | import program from 'commander'; 10 | import replace from 'node-replace'; 11 | import shell from 'shelljs'; 12 | import pjson from '../package.json'; 13 | import path from 'path'; 14 | import { foldersAndFiles } from './config/foldersAndFiles'; 15 | import { filesToModifyContent } from './config/filesToModifyContent'; 16 | import { bundleIdentifiers } from './config/bundleIdentifiers'; 17 | 18 | const devTestRNProject = ''; // For Development eg '/Users/junedomingo/Desktop/RN49' 19 | const __dirname = devTestRNProject || process.cwd(); 20 | const projectName = pjson.name; 21 | const replaceOptions = { 22 | recursive: true, 23 | silent: true, 24 | }; 25 | 26 | function readFile(filePath) { 27 | return new Promise((resolve, reject) => { 28 | fs.readFile(filePath, (err, data) => { 29 | if (err) reject(err); 30 | resolve(data); 31 | }); 32 | }); 33 | } 34 | 35 | function replaceContent(regex, replacement, paths) { 36 | replace({ 37 | regex, 38 | replacement, 39 | paths, 40 | ...replaceOptions, 41 | }); 42 | 43 | for (const filePath of paths) { 44 | console.log(`${filePath.replace(__dirname, '')} ${colors.green('MODIFIED')}`); 45 | } 46 | } 47 | 48 | const deletePreviousBundleDirectory = ({ oldBundleNameDir, shouldDelete }) => { 49 | if (shouldDelete) { 50 | const dir = oldBundleNameDir.replace(/\./g, '/'); 51 | const deleteDirectory = shell.rm('-rf', dir); 52 | Promise.resolve(deleteDirectory); 53 | console.log('Done removing previous bundle directory.'.green); 54 | } else { 55 | Promise.resolve(); 56 | console.log('Bundle directory was not changed. Keeping...'.yellow); 57 | } 58 | }; 59 | 60 | const cleanBuilds = () => { 61 | const deleteDirectories = shell.rm('-rf', [ 62 | path.join(__dirname, 'ios/build/*'), 63 | path.join(__dirname, 'android/.gradle/*'), 64 | path.join(__dirname, 'android/app/build/*'), 65 | path.join(__dirname, 'android/build/*'), 66 | ]); 67 | Promise.resolve(deleteDirectories); 68 | console.log('Done removing builds.'.green); 69 | }; 70 | 71 | readFile(path.join(__dirname, 'android/app/src/main/res/values/strings.xml')) 72 | .then(data => { 73 | const $ = cheerio.load(data); 74 | const currentAppName = $('string[name=app_name]').text(); 75 | const nS_CurrentAppName = currentAppName.replace(/\s/g, ''); 76 | const lC_Ns_CurrentAppName = nS_CurrentAppName.toLowerCase(); 77 | 78 | program 79 | .version('2.4.1') 80 | .arguments('') 81 | .option('-b, --bundleID [value]', 'Set custom bundle identifier eg. "com.junedomingo.travelapp"') 82 | .action(newName => { 83 | const nS_NewName = newName.replace(/\s/g, ''); 84 | const pattern = /^([\p{Letter}\p{Number}])+([\p{Letter}\p{Number}\s]+)$/u; 85 | const lC_Ns_NewAppName = nS_NewName.toLowerCase(); 86 | const bundleID = program.bundleID ? program.bundleID.toLowerCase() : null; 87 | let newBundlePath; 88 | const listOfFoldersAndFiles = foldersAndFiles(currentAppName, newName); 89 | const listOfFilesToModifyContent = filesToModifyContent(currentAppName, newName, projectName); 90 | 91 | if (bundleID) { 92 | newBundlePath = bundleID.replace(/\./g, '/'); 93 | const id = bundleID.split('.'); 94 | const validBundleID = /^([a-zA-Z]([a-zA-Z0-9_])*\.)+[a-zA-Z]([a-zA-Z0-9_])*$/u; 95 | if (id.length < 2) { 96 | return console.log( 97 | 'Invalid Bundle Identifier. Add something like "com.travelapp" or "com.junedomingo.travelapp"' 98 | ); 99 | } 100 | if (!validBundleID.test(bundleID)) { 101 | return console.log( 102 | 'Invalid Bundle Identifier. It must have at least two segments (one or more dots). Each segment must start with a letter. All characters must be alphanumeric or an underscore [a-zA-Z0-9_]' 103 | ); 104 | } 105 | } 106 | 107 | if (!pattern.test(newName)) { 108 | return console.log( 109 | `"${newName}" is not a valid name for a project. Please use a valid identifier name (alphanumeric and space).` 110 | ); 111 | } 112 | 113 | if (newName === currentAppName || newName === nS_CurrentAppName || newName === lC_Ns_CurrentAppName) { 114 | return console.log('Please try a different name.'); 115 | } 116 | 117 | // Move files and folders from ./config/foldersAndFiles.js 118 | const resolveFoldersAndFiles = new Promise(resolve => { 119 | listOfFoldersAndFiles.forEach((element, index) => { 120 | const dest = element.replace(new RegExp(nS_CurrentAppName, 'i'), nS_NewName); 121 | let itemsProcessed = 1; 122 | const successMsg = `/${dest} ${colors.green('RENAMED')}`; 123 | 124 | setTimeout(() => { 125 | itemsProcessed += index; 126 | 127 | if (fs.existsSync(path.join(__dirname, element)) || !fs.existsSync(path.join(__dirname, element))) { 128 | const move = shell.exec( 129 | `git mv "${path.join(__dirname, element)}" "${path.join(__dirname, dest)}" 2>/dev/null` 130 | ); 131 | 132 | if (move.code === 0) { 133 | console.log(successMsg); 134 | } else if (move.code === 128) { 135 | // if "outside repository" error occured 136 | if (shell.mv('-f', path.join(__dirname, element), path.join(__dirname, dest)).code === 0) { 137 | console.log(successMsg); 138 | } else { 139 | console.log("Ignore above error if this file doesn't exist"); 140 | } 141 | } 142 | } 143 | 144 | if (itemsProcessed === listOfFoldersAndFiles.length) { 145 | resolve(); 146 | } 147 | }, 200 * index); 148 | }); 149 | }); 150 | 151 | // Modify file content from ./config/filesToModifyContent.js 152 | const resolveFilesToModifyContent = () => 153 | new Promise(resolve => { 154 | let filePathsCount = 0; 155 | let itemsProcessed = 0; 156 | listOfFilesToModifyContent.map(file => { 157 | filePathsCount += file.paths.length; 158 | 159 | file.paths.map((filePath, index) => { 160 | const newPaths = []; 161 | 162 | setTimeout(() => { 163 | itemsProcessed++; 164 | if (fs.existsSync(path.join(__dirname, filePath))) { 165 | newPaths.push(path.join(__dirname, filePath)); 166 | replaceContent(file.regex, file.replacement, newPaths); 167 | } 168 | if (itemsProcessed === filePathsCount) { 169 | resolve(); 170 | } 171 | }, 200 * index); 172 | }); 173 | }); 174 | }); 175 | 176 | const resolveJavaFiles = () => 177 | new Promise(resolve => { 178 | readFile(path.join(__dirname, 'android/app/src/main/AndroidManifest.xml')).then(data => { 179 | const $ = cheerio.load(data); 180 | const currentBundleID = $('manifest').attr('package'); 181 | const newBundleID = program.bundleID ? bundleID : `com.${lC_Ns_NewAppName}`; 182 | const javaFileBase = '/android/app/src/main/java'; 183 | const newJavaPath = `${javaFileBase}/${newBundleID.replace(/\./g, '/')}`; 184 | const currentJavaPath = `${javaFileBase}/${currentBundleID.replace(/\./g, '/')}`; 185 | 186 | if (bundleID) { 187 | newBundlePath = newJavaPath; 188 | } else { 189 | newBundlePath = newBundleID.replace(/\./g, '/').toLowerCase(); 190 | newBundlePath = `${javaFileBase}/${newBundlePath}`; 191 | } 192 | 193 | const fullCurrentBundlePath = path.join(__dirname, currentJavaPath); 194 | const fullNewBundlePath = path.join(__dirname, newBundlePath); 195 | 196 | // Create new bundle folder if doesn't exist yet 197 | if (!fs.existsSync(fullNewBundlePath)) { 198 | shell.mkdir('-p', fullNewBundlePath); 199 | const move = shell.exec(`git mv "${fullCurrentBundlePath}/"* "${fullNewBundlePath}" 2>/dev/null`); 200 | const successMsg = `${newBundlePath} ${colors.green('BUNDLE INDENTIFIER CHANGED')}`; 201 | 202 | if (move.code === 0) { 203 | console.log(successMsg); 204 | } else if (move.code === 128) { 205 | // if "outside repository" error occured 206 | if (shell.mv('-f', fullCurrentBundlePath + '/*', fullNewBundlePath).code === 0) { 207 | console.log(successMsg); 208 | } else { 209 | console.log(`Error moving: "${currentJavaPath}" "${newBundlePath}"`); 210 | } 211 | } 212 | } 213 | 214 | const vars = { 215 | currentBundleID, 216 | newBundleID, 217 | newBundlePath, 218 | javaFileBase, 219 | currentJavaPath, 220 | newJavaPath, 221 | }; 222 | resolve(vars); 223 | }); 224 | }); 225 | 226 | const resolveBundleIdentifiers = params => 227 | new Promise(resolve => { 228 | let filePathsCount = 0; 229 | const { currentBundleID, newBundleID, newBundlePath, javaFileBase, currentJavaPath, newJavaPath } = params; 230 | 231 | bundleIdentifiers(currentAppName, newName, projectName, currentBundleID, newBundleID, newBundlePath).map( 232 | file => { 233 | filePathsCount += file.paths.length - 1; 234 | let itemsProcessed = 0; 235 | 236 | file.paths.map((filePath, index) => { 237 | const newPaths = []; 238 | if (fs.existsSync(path.join(__dirname, filePath))) { 239 | newPaths.push(path.join(__dirname, filePath)); 240 | 241 | setTimeout(() => { 242 | itemsProcessed += index; 243 | replaceContent(file.regex, file.replacement, newPaths); 244 | if (itemsProcessed === filePathsCount) { 245 | const oldBundleNameDir = path.join(__dirname, javaFileBase, currentBundleID); 246 | resolve({ oldBundleNameDir, shouldDelete: currentJavaPath !== newJavaPath }); 247 | } 248 | }, 200 * index); 249 | } 250 | }); 251 | } 252 | ); 253 | 254 | // * Next section finds all java files and replace package name 255 | // ! Maybe not the best approach 256 | // TODO: Find another solution 257 | const newAndroidPath = path.join(__dirname, newBundlePath); 258 | fs.readdir(newAndroidPath, function(err, files) { 259 | //handling error 260 | if (err) { 261 | return console.log('Unable to scan directory: ' + err); 262 | } 263 | const filePaths = files.map(file => `${newAndroidPath}/${file}`); 264 | replace({ 265 | regex: currentBundleID, 266 | replacement: newBundleID, 267 | paths: filePaths, 268 | ...replaceOptions, 269 | }); 270 | 271 | for (const filePath of filePaths) { 272 | console.log(`${filePath.replace(__dirname, '')} ${colors.green('MODIFIED')}`); 273 | } 274 | }); 275 | // * End of section for replacing package name in all java files 276 | }); 277 | 278 | const rename = () => { 279 | resolveFoldersAndFiles 280 | .then(resolveFilesToModifyContent) 281 | .then(resolveJavaFiles) 282 | .then(resolveBundleIdentifiers) 283 | .then(deletePreviousBundleDirectory) 284 | .then(cleanBuilds) 285 | .then(() => console.log(`APP SUCCESSFULLY RENAMED TO "${newName}"! 🎉 🎉 🎉`.green)) 286 | .then(() => { 287 | if (fs.existsSync(path.join(__dirname, 'ios', 'Podfile'))) { 288 | console.log( 289 | `${colors.yellow('Podfile has been modified, please run "pod install" inside ios directory.')}` 290 | ); 291 | } 292 | }) 293 | .then(() => 294 | console.log( 295 | `${colors.yellow( 296 | 'Please make sure to run "watchman watch-del-all" and "npm start --reset-cache" before running the app. ' 297 | )}` 298 | ) 299 | ); 300 | }; 301 | 302 | rename(); 303 | }) 304 | .parse(process.argv); 305 | if (!process.argv.slice(2).length) program.outputHelp(); 306 | }) 307 | .catch(err => { 308 | if (err.code === 'ENOENT') return console.log('Directory should be created using "react-native init"'); 309 | 310 | return console.log('Something went wrong: ', err); 311 | }); 312 | --------------------------------------------------------------------------------