├── .babelrc ├── .circleci └── config.yml ├── .eslintrc ├── .gitignore ├── .npmignore ├── package.json ├── readme.md ├── src ├── androidPlaystore │ └── index.js ├── bin.js ├── common │ ├── addNpmScript.js │ ├── copy.js │ ├── executeCommand.js │ ├── git.js │ ├── replace.js │ ├── updateJson.js │ └── utils.js ├── index.js ├── iosDeployment │ ├── index.js │ └── pushToITunes.sh ├── notifications │ └── index.js ├── prettierLint │ ├── .eslintrc │ └── index.js ├── provisioningProfiles │ └── index.js ├── reactNativeConfig │ ├── .DS_Store │ ├── android.js │ ├── androidAppIcons │ │ ├── debug │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-ldpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── playstore-icon.png │ │ ├── release │ │ │ └── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-ldpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ │ └── playstore-icon.png │ │ └── staging │ │ │ └── res │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-ldpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ └── playstore-icon.png │ ├── index.js │ ├── iosAppIcons │ │ ├── AppIcon.Debug.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@1x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-76x76@3x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ ├── Icon-Small-50x50@1x.png │ │ │ └── Icon-Small-50x50@2x.png │ │ ├── AppIcon.Release.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@1x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-76x76@3x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ ├── Icon-Small-50x50@1x.png │ │ │ ├── Icon-Small-50x50@2x.png │ │ │ └── ItunesArtwork@2x.png │ │ └── AppIcon.Staging.appiconset │ │ │ ├── Contents.json │ │ │ ├── Icon-App-20x20@1x.png │ │ │ ├── Icon-App-20x20@2x.png │ │ │ ├── Icon-App-20x20@3x.png │ │ │ ├── Icon-App-29x29@1x.png │ │ │ ├── Icon-App-29x29@2x.png │ │ │ ├── Icon-App-29x29@3x.png │ │ │ ├── Icon-App-40x40@1x.png │ │ │ ├── Icon-App-40x40@2x.png │ │ │ ├── Icon-App-40x40@3x.png │ │ │ ├── Icon-App-57x57@1x.png │ │ │ ├── Icon-App-57x57@2x.png │ │ │ ├── Icon-App-60x60@1x.png │ │ │ ├── Icon-App-60x60@2x.png │ │ │ ├── Icon-App-60x60@3x.png │ │ │ ├── Icon-App-72x72@1x.png │ │ │ ├── Icon-App-72x72@2x.png │ │ │ ├── Icon-App-76x76@1x.png │ │ │ ├── Icon-App-76x76@2x.png │ │ │ ├── Icon-App-76x76@3x.png │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ ├── Icon-Small-50x50@1x.png │ │ │ ├── Icon-Small-50x50@2x.png │ │ │ └── ItunesArtwork@2x.png │ ├── reactNative.js │ └── xcodeProject.js └── reactNativeInit │ └── index.js ├── test └── test.js └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "transform-class-properties", 4 | "transform-object-rest-spread", 5 | ["babel-plugin-root-import", { 6 | "rootPathSuffix": "src" 7 | }] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build-test-deploy: 4 | docker: 5 | - image: circleci/node:10-browsers 6 | steps: 7 | - checkout 8 | - run: 9 | name: Add node modules to $PATH 10 | command: echo 'export PATH=${PATH}:${HOME}/${CIRCLE_PROJECT_REPONAME}/node_modules/.bin' >> $BASH_ENV 11 | - restore_cache: 12 | name: Restore Yarn Package Cache 13 | keys: 14 | - yarn-packages-{{ checksum "yarn.lock" }} 15 | - run: 16 | name: Yarn install 17 | command: yarn install --pure-lockfile 18 | - save_cache: 19 | key: yarn-packages-{{ checksum "yarn.lock" }} 20 | name: Save Yarn Package Cache 21 | paths: 22 | - ~/.cache/yarn 23 | - run: 24 | name: test 25 | command: yarn ci 26 | workflows: 27 | version: 2 28 | workflow: 29 | jobs: 30 | - build-test-deploy 31 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | extends: 2 | - eslint-config-airbnb-base 3 | - prettier 4 | 5 | plugins: 6 | - prettier 7 | 8 | parser: 9 | babel-eslint 10 | 11 | settings: 12 | ecmascript: 6 13 | 14 | ecmaFeatures: 15 | modules: true 16 | destructuring: true 17 | classes: true 18 | forOf: true 19 | blockBindings: true 20 | arrowFunctions: true 21 | 22 | env: 23 | browser: true 24 | mocha: true 25 | 26 | rules: 27 | arrow-body-style: 0 28 | func-style: 0 29 | func-names: 0 30 | comma-dangle: 0 31 | no-console: 0 32 | no-param-reassign: 0 33 | linebreak-style: 0 34 | import/no-extraneous-dependencies: 0 35 | import/no-unresolved: 0 36 | import/extensions: 0 37 | import/prefer-default-export: 0 38 | import/no-named-as-default: 0 39 | import/no-commonjs: 2 40 | space-return-throw-case: 0 41 | object-shorthand: 0 42 | complexity: 0 43 | strict: [2, "never"] 44 | no-confusing-arrow: 0 45 | prettier/prettier: ["error", {"trailingComma": "all", "singleQuote": true, "semi": false, "printWidth": 180 }] 46 | import/no-absolute-path: 0 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git 28 | node_modules 29 | 30 | # Optional npm cache directory 31 | .npm 32 | 33 | # Optional REPL history 34 | .node_repl_history 35 | 36 | dist 37 | 38 | build 39 | 40 | .DS_Store 41 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/.npmignore -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rn-scaffold", 3 | "version": "0.0.16", 4 | "description": "", 5 | "repository": { 6 | "url": "https://github.com/z-dev/rn-scaffold.git" 7 | }, 8 | "license": "ISC", 9 | "bin": { 10 | "rn-scaffold": "./build/bin.js" 11 | }, 12 | "scripts": { 13 | "build": "rm -rf ./build && neutrino build --use neutrino-preset-node && cp ./src/bin.js ./build/ && find src/ | grep -v -i .js$ | cpio -pdm ./build", 14 | "check:node": "check-node-version --node \">=8.1.2 <9\"", 15 | "ci": "yarn lint && yarn test", 16 | "clean": "rm -rf dist", 17 | "precommit": "lint-staged && yarn lint", 18 | "eslint-check": "eslint --print-config .eslintrc | eslint-config-prettier-check", 19 | "format:js": "yarn prettier -- \"src/**/*.js\"", 20 | "lint": "eslint ./src ./test --ext=js", 21 | "prepublish": "in-publish && yarn build || not-in-publish", 22 | "sort:package:json": "sort-package-json", 23 | "start": "neutrino start --use neutrino-preset-node", 24 | "start:built": "forever build/index.js", 25 | "start:debug": "yarn start -- --debug", 26 | "start:docker": "docker build -t lead-finder-server . && docker run --rm -it lead-finder-server", 27 | "test": "neutrino test --use neutrino-preset-node neutrino-preset-mocha", 28 | "test:watch": "nodemon -w src -w test --exec 'yarn test'", 29 | "prettier": "prettier --single-quote --trailing-comma all --no-semi --print-width 180 --write" 30 | }, 31 | "dependencies": { 32 | "babel-plugin-root-import": "^5.1.0", 33 | "fs-extra": "^4.0.1", 34 | "git-state": "^4.0.0", 35 | "gradle-to-js": "^1.0.1", 36 | "indent-string": "^3.2.0", 37 | "json-stringify-pretty-compact": "^1.0.4", 38 | "jsonfile": "^3.0.1", 39 | "lodash": "^4.2.1", 40 | "plist": "^2.1.0", 41 | "prompt-promise": "^1.0.3", 42 | "replace-in-file": "^2.6.3", 43 | "xcode": "^0.9.3", 44 | "yargs": "^8.0.2" 45 | }, 46 | "devDependencies": { 47 | "babel-eslint": "^7.2.3", 48 | "babel-plugin-transform-class-properties": "^6.23.0", 49 | "babel-plugin-transform-object-rest-spread": "^6.22.0", 50 | "chai": "^4.0.1", 51 | "chai-moment": "^0.1.0", 52 | "check-node-version": "^2.1.0", 53 | "eslint": "^4.5.0", 54 | "eslint-config-airbnb": "^15.1.0", 55 | "eslint-config-airbnb-base": "^11.3.2", 56 | "eslint-config-prettier": "^2.3.0", 57 | "eslint-plugin-import": "^2.7.0", 58 | "eslint-plugin-jsx-a11y": "^5.1.1", 59 | "eslint-plugin-prettier": "^2.2.0", 60 | "eslint-plugin-react": "^7.3.0", 61 | "forever": "^0.15.3", 62 | "husky": "^0.13.4", 63 | "in-publish": "^2.0.0", 64 | "lint-staged": "^3.6.1", 65 | "neutrino": "^5.9.0", 66 | "neutrino-preset-mocha": "^5.9.0", 67 | "neutrino-preset-node": "^5.9.1", 68 | "nodemon": "^1.8.1", 69 | "prettier": "^1.6.1", 70 | "sort-package-json": "^1.7.1" 71 | }, 72 | "engines": { 73 | "node": ">= 8.1.2" 74 | }, 75 | "engine-strict": true, 76 | "lint-staged": { 77 | "src/**/*.js": [ 78 | "yarn run format:js", 79 | "git add" 80 | ], 81 | "package.json": [ 82 | "yarn sort:package:json", 83 | "git add" 84 | ] 85 | }, 86 | "neutrino": { 87 | "options": { 88 | "mocha": { 89 | "recursive": true 90 | } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## rn-scaffold 2 | 3 | *Warning*: This is in beta: we've successfully used it with one or two projects though. 4 | 5 | rn-scaffold is a tool to help automate setting up the common parts of a react-native project: 6 | 7 | * Different environments, debug, staging and release 8 | * Provisioning profiles using match 9 | * Deployment to Testflight and Playstore 10 | * Notifications with firebase 11 | 12 | 13 | It's opinionated, designed for real-life apps. We built it after building 5+ apps and doing the same steps over and over and screwing them up. 14 | 15 | ## Getting started 16 | 17 | Install rn scaffold using: `npm install -g rn-scaffold` 18 | 19 | In general we'll only be supporting the last minor version of the previous version of React Native (since this one is the most stable). 20 | 21 | ## Usage 22 | 23 | If in doubt commands should be run in order listed below to avoid any errors! 24 | 25 | `rn-scaffold react-native-init` 26 | - runs react-native init 27 | - renames your project correctly and updates the android package / file structure 28 | - to switch react-native version use the flag `--react-native-version` 29 | 30 | `rn-scaffold prettier-lint` 31 | - Adds eslint, prettier and lint-staged to your project. 32 | 33 | `rn-scaffold react-native-config` 34 | - adds different build environments debug, staging and release to ios and android. 35 | - adds different bundleIds and app names per environment, e.g. com.myApp.debug, myApp debug ect 36 | - adds different app icons per environment 37 | - adds [`react-native-schemes-manager`](https://github.com/Thinkmill/react-native-schemes-manager) to manage adding new environment to ios project 38 | - adds code snippets to pass current environmet though intialProps into react-native app to allow correct config to be loaded 39 | - add generates apk signing key stores for android environments 40 | 41 | `rn-scaffold provisioning-profiles` (Requires manual steps that user needs complete, see logs for details) 42 | - generates provisioning profiles per environment (debug, staging, release) for ios app on developer.apple.com 43 | - syncs generated provisioning profiles to local machine 44 | 45 | 46 | `rn-scaffold ios-deployment` (Requires `rn-scaffold provisioning-profiles` command to have been run first) 47 | - adds deployment npm scripts for staging and release builds of app to app store 48 | - adds `pushToITunes.sh` script to build ipa files and push them to itunes connect 49 | - adds cocoa pods to app to create .xcworkspace file to generate ipa from 50 | 51 | 52 | `rn-scaffold android-deployment` 53 | - adds deployment npm scripts for staging and release builds of app to play store 54 | 55 | `rn-scaffold notifications` (Requires `rn-scaffold provisioning-profiles` to have been run and cocoa pods to be installed. Requires a lot of manual user steps, see logs or details) 56 | - generates ios certificates for push notifications per environment (debug, staging, release) 57 | - adds FirebaseMessaging pod and installs react-native-fcm 58 | - adds code to ios to handle multiple bundleIds for GoogleService-Info.plist files 59 | 60 | ## Running Locally 61 | 62 | You can test local changes by doing something like: 63 | ``` 64 | (cd ../../scaffolding && npm i && npm build) && node ../../scaffolding/build/bin.js react-native-config 65 | ``` 66 | -------------------------------------------------------------------------------- /src/androidPlaystore/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import executeCommand, { checkCommandsExist } from '~/common/executeCommand' 3 | import addNpmScript from '~/common/addNpmScript' 4 | import { copyFiles } from '~/common/copy' 5 | import prompt from 'prompt-promise' 6 | import { parseFile as parseGradleFile } from 'gradle-to-js/lib/parser' 7 | 8 | const apkFolder = 'android/app/build/outputs/apk' 9 | const buildApkCommand = buildType => `(cd android && ./gradlew assemble${buildType})` 10 | const supplyCommand = (buildType, playServiceAccount, applicationId) => { 11 | return `fastlane supply --apk ${apkFolder}/app-${buildType}.apk --track alpha --json_key ${playServiceAccount} --package_name ${applicationId}.${buildType}` 12 | } 13 | 14 | const applicationIdFromBuildGradle = async () => { 15 | const gradleBuild = await parseGradleFile('./android/app/build.gradle') 16 | return _.get(gradleBuild, 'android.defaultConfig.applicationId') 17 | } 18 | 19 | const deployScript = (buildType, applicationId) => { 20 | return `${buildApkCommand(_.upperFirst(buildType))} && npm run android:increment && ${supplyCommand(buildType, './android/playServiceAccount.json', applicationId)}` 21 | } 22 | 23 | export default async () => { 24 | checkCommandsExist(['fastlane']) 25 | 26 | const applicationId = await applicationIdFromBuildGradle() 27 | const serviceAccountFile = await prompt( 28 | `We're going to setup supply to push Android APKs to play store. 29 | Follow these instructions to generate the .json file. 30 | 31 | https://github.com/fastlane/fastlane/tree/master/supply#setup 32 | 33 | .json filepath: `, 34 | ) 35 | 36 | copyFiles(serviceAccountFile, './android/playServiceAccount.json') 37 | 38 | executeCommand(buildApkCommand('Staging')) 39 | executeCommand(buildApkCommand('Release')) 40 | 41 | executeCommand('npm install react-native-version') 42 | 43 | addNpmScript('android:increment', `react-native-version --target android --increment-build`) 44 | addNpmScript('deploy:android:staging', `npm run android:increment && ${deployScript('staging', applicationId)}`) 45 | addNpmScript('deploy:android:release', `npm run android:increment && ${deployScript('release', applicationId)}`) 46 | 47 | console.log( 48 | `Your turn! 49 | 50 | Create an app in google play store: https://play.google.com/apps/publish/ 51 | 52 | Go to 'App Releases' on left, hit 'Manage Alpha' and create a release. 53 | 54 | ** You must 'Opt Out' of the google code signing ** 55 | 56 | Manually upload the staging apk from this folder: ${apkFolder} 57 | 58 | 59 | 60 | Run npm run deploy:android:staging to test automatic deployments. 61 | 62 | Repeat the same steps for release`, 63 | ) 64 | } 65 | -------------------------------------------------------------------------------- /src/bin.js: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env node 2 | 3 | /* eslint-disable import/no-commonjs */ 4 | require('./index.js') 5 | -------------------------------------------------------------------------------- /src/common/addNpmScript.js: -------------------------------------------------------------------------------- 1 | import updateJson, { getFile } from './updateJson' 2 | 3 | const DONT_PRINT = false 4 | 5 | export default (name, command) => { 6 | console.log(`\nAdding npm script: "${name}": "${command}" \n`) 7 | try { 8 | const packaged = getFile() 9 | updateJson({ scripts: { ...packaged.scripts, [name]: command } }, './package.json', DONT_PRINT) 10 | } catch (e) { 11 | if (e.message === "ENOENT, no such file or directory 'package.json'") { 12 | throw e 13 | } else { 14 | throw e 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/common/copy.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | 3 | export const copyFiles = (fromPath, toPath) => { 4 | console.log(`Copying from: ${fromPath} to: ${toPath}`) 5 | fs.copySync(fromPath, toPath) 6 | } 7 | -------------------------------------------------------------------------------- /src/common/executeCommand.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import { execSync } from 'child_process' 3 | 4 | export default command => { 5 | console.log(`\nExecuting: ${command} \n`) 6 | execSync(command, { stdio: [0, 1, 2] }) 7 | } 8 | 9 | export const doesCommandExist = command => { 10 | try { 11 | execSync(command, { stdio: [] }) 12 | } catch (e) { 13 | return e.status <= 1 14 | } 15 | return true 16 | } 17 | 18 | export const checkCommandsExist = commands => { 19 | const commandsWithErrors = _.reject(commands, doesCommandExist) 20 | if (!_.isEmpty(commandsWithErrors)) { 21 | throw new Error(`Could not find prerequisite commands on path: ${commandsWithErrors.join(', ')}`) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/common/git.js: -------------------------------------------------------------------------------- 1 | import { checkSync } from 'git-state' 2 | 3 | export const isClean = (path = '.') => { 4 | const checkResult = checkSync(path) 5 | const changes = checkResult.dirty + checkResult.untracked 6 | return changes === 0 7 | } 8 | 9 | export const errorIfNotClean = (path = '.') => { 10 | if (!isClean(path)) { 11 | throw new Error('You have modifications / untracked changes in git. To run scaffold anyway use: --allow-dirty-git') 12 | } 13 | } 14 | 15 | export const printResetInstructions = () => { 16 | console.log('To rollback these changes in git you can run: git reset --hard && git clean -f -d') 17 | } 18 | -------------------------------------------------------------------------------- /src/common/replace.js: -------------------------------------------------------------------------------- 1 | import replace from 'replace-in-file' 2 | 3 | export const replaceInFile = (file, toReplace, newString) => { 4 | console.log(`\nReplacing ${newString} after ${toReplace} in: ${file}`) 5 | const options = { 6 | files: file, 7 | from: toReplace, 8 | to: newString, 9 | } 10 | replace.sync(options) 11 | } 12 | 13 | export const addInFileAfter = (file, toReplace, newString) => { 14 | console.log(`\nAdding ${newString} after ${toReplace} in: ${file}`) 15 | 16 | const options = { 17 | files: file, 18 | from: toReplace, 19 | to: `${toReplace} ${newString}`, 20 | } 21 | replace.sync(options) 22 | } 23 | 24 | export const addInFileBefore = (file, toReplace, newString) => { 25 | console.log(`\nAdding ${newString} before ${toReplace} in: ${file}`) 26 | 27 | const options = { 28 | files: file, 29 | from: toReplace, 30 | to: `${newString}${toReplace}`, 31 | } 32 | replace.sync(options) 33 | } 34 | -------------------------------------------------------------------------------- /src/common/updateJson.js: -------------------------------------------------------------------------------- 1 | import jsonfile from 'jsonfile' 2 | import stringify from 'json-stringify-pretty-compact' 3 | 4 | export const getFile = (packageFile = './package.json') => jsonfile.readFileSync(packageFile) 5 | 6 | export default (toMergeIn, packageFile = './package.json', print = true) => { 7 | if (print) { 8 | console.log(`\n adding ${stringify(toMergeIn)} to ${packageFile}\n`) 9 | } 10 | const packaged = getFile() 11 | const newPackaged = { ...packaged, ...toMergeIn } 12 | jsonfile.writeFileSync(packageFile, newPackaged, { spaces: 2 }) 13 | } 14 | -------------------------------------------------------------------------------- /src/common/utils.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | 3 | export const arrayWrap = x => { 4 | if (_.isArray(x)) { 5 | return x 6 | } 7 | if (_.isNil(x)) { 8 | return [] 9 | } 10 | return [x] 11 | } 12 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash' 2 | import yargs from 'yargs' 3 | import { errorIfNotClean, printResetInstructions } from '~/common/git' 4 | import prettierLint from './prettierLint' 5 | import reactNativeInit from './reactNativeInit' 6 | import reactNativeConfig from './reactNativeConfig' 7 | import addIosDeployment from './iosDeployment' 8 | import androidPlaystore from './androidPlaystore' 9 | import setUpProvisioningProfiles from './provisioningProfiles' 10 | import notifications from './notifications' 11 | 12 | const firstArg = _.get(yargs.argv, '_[0]') 13 | const run = async () => { 14 | const isReactNativeInit = firstArg === 'react-native-init' 15 | try { 16 | if (!yargs.argv.allowDirtyGit && !isReactNativeInit) { 17 | errorIfNotClean() 18 | } 19 | if (firstArg === 'prettier-lint') { 20 | prettierLint() 21 | } else if (isReactNativeInit) { 22 | await reactNativeInit(yargs.argv) 23 | } else if (firstArg === 'react-native-config') { 24 | await reactNativeConfig() 25 | } else if (firstArg === 'ios-deployment') { 26 | await addIosDeployment() 27 | } else if (firstArg === 'android-deployment') { 28 | await androidPlaystore() 29 | } else if (firstArg === 'provisioning-profiles') { 30 | await setUpProvisioningProfiles() 31 | } else if (firstArg === 'notifications') { 32 | await notifications() 33 | } else { 34 | console.error(`Could not find scaffold: ${firstArg}`) 35 | process.exit(1) 36 | } 37 | printResetInstructions() 38 | process.exit(0) 39 | } catch (e) { 40 | console.error(e) 41 | 42 | printResetInstructions() 43 | process.exit(1) 44 | } 45 | } 46 | 47 | run() 48 | -------------------------------------------------------------------------------- /src/iosDeployment/index.js: -------------------------------------------------------------------------------- 1 | import { replaceInFile } from '~/common/replace' 2 | import { copyFiles } from '~/common/copy' 3 | import addNpmScript from '~/common/addNpmScript' 4 | import { findReactNativeProjectName } from '~/reactNativeConfig/reactNative' 5 | import path from 'path' 6 | import executeCommand from '~/common/executeCommand' 7 | import prompt from 'prompt-promise' 8 | 9 | export default async () => { 10 | console.log('Adding npm deployment scripts') 11 | 12 | addNpmScript('deploy:ios:staging', 'npm run ios:increment && CONFIGURATION=Staging bin/pushToITunes.sh') 13 | addNpmScript('deploy:ios:release', 'npm run ios:increment && CONFIGURATION=Release bin/pushToITunes.sh') 14 | addNpmScript('ios:increment', `react-native-version --target ios --increment-build`) 15 | 16 | const xcodeProjectName = findReactNativeProjectName() 17 | 18 | console.log('Building ios deployment script') 19 | 20 | copyFiles(path.join(__dirname, 'src/iosDeployment/pushToITunes.sh'), `./bin/pushToITunes.sh`) 21 | 22 | replaceInFile('./bin/pushToITunes.sh', 'WORKSPACE_FILE="ios/.xcworkspace/"', `WORKSPACE_FILE="ios/${xcodeProjectName}.xcworkspace/"`) 23 | replaceInFile('./bin/pushToITunes.sh', 'SCHEME=""', `SCHEME="${xcodeProjectName}"`) 24 | 25 | executeCommand('chmod u+x ./bin/pushToITunes.sh') 26 | 27 | console.log('installing cocoa pods') 28 | executeCommand('cd ios && pod init') 29 | 30 | replaceInFile('./ios/Podfile', "# platform :ios, '9.0'", "platform :ios, '9.0'") 31 | 32 | // prettier-ignore 33 | replaceInFile( 34 | './ios/Podfile', 35 | '# Uncomment the next line to define a global platform for your project', 36 | `project '${xcodeProjectName}.xcodeproj/'` + 37 | '\n' + 38 | '\n' + 39 | '# Uncomment the next line to define a global platform for your project' 40 | ) 41 | // pod init is creating 2 instances of the tvOS pod commands so one of them is getting removed here 42 | replaceInFile( 43 | './ios/Podfile', 44 | `target '${xcodeProjectName}-tvOS' do 45 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks 46 | # use_frameworks! 47 | 48 | # Pods for ${xcodeProjectName}-tvOS 49 | 50 | target '${xcodeProjectName}-tvOSTests' do 51 | inherit! :search_paths 52 | # Pods for testing 53 | end 54 | 55 | end`, 56 | '', 57 | ) 58 | 59 | executeCommand('cd ios && pod install') 60 | 61 | console.log("Go to https://itunesconnect.apple.com go to 'My Apps' and add your apps (with the correct bundle ids).") 62 | await prompt('Have you completed the previous steps? (y/n)') 63 | 64 | console.log('deployment scripts added look for "deploy:ios:staging" and "deploy:ios:release" in package.json') 65 | } 66 | -------------------------------------------------------------------------------- /src/iosDeployment/pushToITunes.sh: -------------------------------------------------------------------------------- 1 | CONFIGURATION=$CONFIGURATION||"Staging" 2 | BUILD_DIR=ios/release 3 | IPA_FILE_NAME="app.ipa" 4 | IPA="$BUILD_DIR/$IPA_FILE_NAME" 5 | WORKSPACE_FILE="ios/.xcworkspace/" 6 | SCHEME="" 7 | echo "Configuration: $CONFIGURATION" 8 | echo "IPA: $IPA" 9 | echo "IPA_FILE_NAME: $IPA_FILE_NAME" 10 | 11 | fastlane gym --workspace $WORKSPACE_FILE --scheme $SCHEME --configuration $CONFIGURATION --output_directory $BUILD_DIR --output_name $IPA_FILE_NAME && \ 12 | fastlane deliver --ipa "$IPA" --force 13 | -------------------------------------------------------------------------------- /src/notifications/index.js: -------------------------------------------------------------------------------- 1 | import executeCommand from '~/common/executeCommand' 2 | import prompt from 'prompt-promise' 3 | import { replaceInFile, addInFileAfter } from '~/common/replace' 4 | import { findReactNativeProjectName } from '~/reactNativeConfig/reactNative' 5 | 6 | export default async () => { 7 | executeCommand('npm install react-native-fcm --save') 8 | executeCommand('react-native link') 9 | 10 | const appId = await prompt('Please enter your bundleId without the config suffix e.g. "com.zdev.myApp" not "com.zdev.myApp.debug": ') 11 | const userName = await prompt('Please enter you AppleID username: ') 12 | 13 | const projectName = findReactNativeProjectName() 14 | const notificationCertificates = './notificationCertificates' 15 | executeCommand(`mkdir -p ${notificationCertificates}`) 16 | executeCommand(`fastlane pem -a ${appId}.debug -u ${userName} --force --output_path ${notificationCertificates}`) 17 | executeCommand(`fastlane pem -a ${appId}.staging -u ${userName} --force --output_path ${notificationCertificates}`) 18 | executeCommand(`fastlane pem -a ${appId} -u ${userName} --force --output_path ${notificationCertificates}`) 19 | 20 | console.log('You will need to rebuild your provisioning profiles on https://developer.apple.com/account/ios/profile/ Simply click on the profiles and select edit -> generate') 21 | const response = await prompt('Have you completed the previously logged steps? (y/n)') 22 | if (response !== 'y') { 23 | executeCommand('git reset --hard && git clean -f -d') 24 | console.log('all changes reset please try agian') 25 | process.exit(1) 26 | } 27 | 28 | executeCommand('npm run apple:sync') 29 | 30 | addInFileAfter( 31 | './ios/Podfile', 32 | `# Pods for ${projectName}`, 33 | `\n 34 | pod 'FirebaseMessaging'`, 35 | ) 36 | 37 | executeCommand('cd ios && pod install') 38 | 39 | // prettier-ignore 40 | replaceInFile( 41 | `./ios/${projectName}/AppDelegate.h`, 42 | `@interface AppDelegate : UIResponder `, 43 | '@import UserNotifications;' + 44 | '\n' + 45 | '@interface AppDelegate : UIResponder ' 46 | ) 47 | 48 | // prettier-ignore 49 | addInFileAfter( 50 | `./ios/${projectName}/AppDelegate.m`, 51 | '#import "AppDelegate.h"', 52 | '\n' + 53 | '#import "RNFIRMessaging.h"' + 54 | '\n' + 55 | '#import ' 56 | ) 57 | 58 | // prettier-ignore 59 | addInFileAfter( 60 | `./ios/${projectName}/AppDelegate.m`, 61 | '[self.window makeKeyAndVisible];', 62 | 63 | `\nNSString *filePath = NULL; 64 | 65 | if([@"DEBUG" isEqualToString: ENVIRONMENT]){ 66 | filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Debug" ofType:@"plist"]; 67 | } 68 | else if([@"STAGING" isEqualToString: ENVIRONMENT]){ 69 | filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Staging" ofType:@"plist"]; 70 | } 71 | else { 72 | filePath = [[NSBundle mainBundle] pathForResource:@"GoogleService-Info-Release" ofType:@"plist"]; 73 | } 74 | FIROptions *options = [[FIROptions alloc] initWithContentsOfFile:filePath]; 75 | [FIRApp configureWithOptions:options]; [[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];` 76 | ) 77 | 78 | replaceInFile( 79 | `./ios/${projectName}/AppDelegate.m`, 80 | '@end', 81 | `- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler 82 | { 83 | [RNFIRMessaging willPresentNotification:notification withCompletionHandler:completionHandler]; 84 | } 85 | 86 | - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler 87 | { 88 | [RNFIRMessaging didReceiveNotificationResponse:response withCompletionHandler:completionHandler]; 89 | } 90 | 91 | @end`, 92 | ) 93 | 94 | console.log(`Now inside xcode you need to enable 95 | Push Notifications & 96 | Background Modes > Remote notifications. 97 | These can be found in your projects Capabilities tab`) 98 | 99 | await prompt('Have you completed the previously logged steps? (y/n)') 100 | 101 | addInFileAfter('./android/build.gradle', "classpath 'com.android.tools.build:gradle:2.2.3'", "\nclasspath 'com.google.gms:google-services:3.0.0'") 102 | 103 | addInFileAfter('./android/app/build.gradle', 'apply plugin: "com.android.application"', "\napply plugin: 'com.google.gms.google-services'") 104 | 105 | addInFileAfter( 106 | './android/app/src/main/AndroidManifest.xml', 107 | 'android:theme="@style/AppTheme">', 108 | `\n 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | `, 119 | ) 120 | 121 | addInFileAfter('./android/app/build.gradle', 'dependencies {', "\ncompile 'com.google.firebase:firebase-core:10.0.1'") 122 | 123 | addInFileAfter('./android/app/src/main/AndroidManifest.xml', 'android:windowSoftInputMode="adjustResize"', '\nandroid:launchMode="singleTop"') 124 | 125 | addInFileAfter( 126 | './android/app/src/main/AndroidManifest.xml', 127 | '', 128 | `\n 129 | 130 | 131 | `, 132 | ) 133 | 134 | console.log(`Now you need to create a firebase project for each app environment: debug, staging and release. Then add your app for both ios and android for each project.`) 135 | console.log( 136 | `You will need to download 3 GoogleService-Info.plist files, each one should be renamed to include -Debug, -Staging and -Release according to the build environment it represents`, 137 | ) 138 | console.log(`place these files in your projects ios/your_app (inside xcode & in you porjects folder hierarchy) where your current info.plist file is found`) 139 | console.log(`For android you will need to create 3 folders debug, staging and release under android/app/src and drag the corresponding google-service.json file into it`) 140 | console.log(`now follow the steps found here under usage https://github.com/evollu/react-native-fcm to start sending notifications`) 141 | console.log(`If you would like to undo the changes made by this command just run this command: git reset --hard && git clean -f -d`) 142 | } 143 | -------------------------------------------------------------------------------- /src/prettierLint/.eslintrc: -------------------------------------------------------------------------------- 1 | extends: 2 | - airbnb 3 | - prettier 4 | 5 | plugins: 6 | - prettier 7 | 8 | parser: 9 | babel-eslint 10 | 11 | settings: 12 | ecmascript: 6 13 | 14 | ecmaFeatures: 15 | modules: true 16 | destructuring: true 17 | classes: true 18 | forOf: true 19 | blockBindings: true 20 | arrowFunctions: true 21 | 22 | env: 23 | browser: true 24 | mocha: true 25 | 26 | rules: 27 | arrow-body-style: 0 28 | func-style: 0 29 | func-names: 0 30 | comma-dangle: 0 31 | no-console: 0 32 | no-param-reassign: 0 33 | linebreak-style: 0 34 | import/no-extraneous-dependencies: 0 35 | import/no-unresolved: 0 36 | import/extensions: 0 37 | import/prefer-default-export: 0 38 | import/no-named-as-default: 0 39 | import/no-commonjs: 2 40 | space-return-throw-case: 0 41 | object-shorthand: 0 42 | complexity: 0 43 | strict: [2, "never"] 44 | no-confusing-arrow: 0 45 | prettier/prettier: ["error", {"trailingComma": "all", "singleQuote": true, "semi": false, "printWidth": 180 }] 46 | import/no-absolute-path: 0 47 | -------------------------------------------------------------------------------- /src/prettierLint/index.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs-extra' 2 | import path from 'path' 3 | import addNpmScript from '~/common/addNpmScript' 4 | import updateJson from '~/common/updateJson' 5 | import executeCommand from '~/common/executeCommand' 6 | 7 | export default () => { 8 | executeCommand('npm install --save-dev prettier babel-eslint eslint-config-prettier eslint-plugin-prettier husky lint-staged sort-package-json') 9 | 10 | executeCommand(`( 11 | export PKG=eslint-config-airbnb; 12 | npm info "$PKG@latest" peerDependencies --json | command sed 's/[{},]//g ; s/: /@/g' | xargs npm install --save-dev "$PKG@latest" 13 | )`) 14 | 15 | addNpmScript('prettier', 'prettier --single-quote --trailing-comma all --no-semi --print-width 180 --write') 16 | 17 | addNpmScript('format:js', 'npm run prettier -- "src/**/*.js"') 18 | 19 | addNpmScript('precommit', 'lint-staged && npm run lint') 20 | 21 | addNpmScript('lint', 'eslint ./src --ext=js') 22 | 23 | updateJson( 24 | { 25 | 'lint-staged': { 26 | 'src/**/*.js': ['npm run prettier --', 'git add'], 27 | 'package.json': ['sort-package-json', 'git add'], 28 | }, 29 | }, 30 | './package.json', 31 | ) 32 | 33 | fs.copySync(path.join(__dirname, 'src/prettierLint/.eslintrc'), './.eslintrc') 34 | 35 | console.log('Finished Adding Prettier') 36 | } 37 | -------------------------------------------------------------------------------- /src/provisioningProfiles/index.js: -------------------------------------------------------------------------------- 1 | import executeCommand, { checkCommandsExist } from '~/common/executeCommand' 2 | import prompt from 'prompt-promise' 3 | import addNpmScript from '~/common/addNpmScript' 4 | 5 | export default async () => { 6 | console.log('Checking prerequisite installs') 7 | checkCommandsExist(['fastlane', 'xcode-select']) 8 | 9 | const appId = await prompt('Please enter your bundleId without the config suffix e.g. "com.zdev.myApp" not "com.zdev.myApp.debug": ') 10 | const userName = await prompt('Please enter you AppleID username: ') 11 | 12 | console.log('Please go to https://developer.apple.com/account and access Certificates, Identifiers & Profiles') 13 | console.log(`Under Identifiers > App IDs. Add new App IDs for ${appId}.debug, ${appId}.staging and ${appId}`) 14 | console.log( 15 | "If there isn't one already. Add a IOS device to the Devices tab in Certificates, Identifiers & Profiles, you device UUID can be found in xcode under window > devices when it is plugged in", 16 | ) 17 | 18 | const response = await prompt('Have you completed the previously logged steps? (y/n)') 19 | 20 | if (response !== 'y') { 21 | process.exit(1) 22 | } 23 | 24 | executeCommand(`fastlane match init`) 25 | 26 | console.log('Creating development certificates') 27 | 28 | executeCommand(`fastlane match development -a ${appId}.debug -u ${userName}`) 29 | executeCommand(`fastlane match development -a ${appId}.staging -u ${userName}`) 30 | executeCommand(`fastlane match development -a ${appId} -u ${userName}`) 31 | 32 | console.log('Creating AppStore certificates') 33 | 34 | executeCommand(`fastlane match appstore -a ${appId}.staging -u ${userName}`) 35 | executeCommand(`fastlane match appstore -a ${appId} -u ${userName}`) 36 | 37 | addNpmScript( 38 | 'apple:sync', 39 | `fastlane match development --app_identifier ${appId}.staging,${appId}.debug,${appId}.staging && fastlane match appstore --readonly --app_identifier ${appId}.staging,${appId}.staging`, 40 | ) 41 | 42 | console.log('Other team members need to run `npm run apple:sync` after they check-out the project.') 43 | console.log( 44 | 'Open xcode, go to project settings -> general -> untick Automatically manage signing -> select the match provisioning profiles for each build environment \n\n For debug: select match Development. \n For Staging & Release: select match AppStore', 45 | ) 46 | await prompt('Have you completed the previous steps? (y/n)') 47 | } 48 | -------------------------------------------------------------------------------- /src/reactNativeConfig/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/.DS_Store -------------------------------------------------------------------------------- /src/reactNativeConfig/android.js: -------------------------------------------------------------------------------- 1 | import crypto from 'crypto' 2 | import { addInFileAfter, addInFileBefore, replaceInFile } from '~/common/replace' 3 | import executeCommand from '~/common/executeCommand' 4 | import fs from 'fs-extra' 5 | import indentString from 'indent-string' 6 | 7 | /* eslint-disable no-useless-escape */ 8 | const setAppNameForBuildType = (appName, buildType) => { 9 | addInFileAfter('./android/app/build.gradle', `${buildType} {`, indentString(`\nresValue "string", "app_name", "${appName}"`, 12)) 10 | } 11 | 12 | const addApplicationIdSuffixForBuildType = buildType => { 13 | addInFileAfter('./android/app/build.gradle', `${buildType} {`, indentString(`\napplicationIdSuffix ".${buildType}"`, 12)) 14 | } 15 | 16 | export const applicationIdSuffixPerEnvironment = () => { 17 | addApplicationIdSuffixForBuildType('debug') 18 | addApplicationIdSuffixForBuildType('staging') 19 | } 20 | 21 | export const appNameSuffixPerEnvironment = appName => { 22 | replaceInFile('./android/app/src/main/res/values/strings.xml', /.+<\/string>/, '') 23 | 24 | setAppNameForBuildType(`${appName} Debug`, 'debug') 25 | setAppNameForBuildType(`${appName} Staging`, 'staging') 26 | setAppNameForBuildType(appName, 'release') 27 | } 28 | 29 | const generateKeystore = (gradleFile, appId, buildType) => { 30 | const storePassword = crypto.randomBytes(64).toString('base64') 31 | const keyPassword = crypto.randomBytes(64).toString('base64') 32 | const keyStoreFile = `keyStores/${buildType}.keystore` 33 | 34 | executeCommand( 35 | `keytool -genkey -v -keystore ./android/app/${keyStoreFile} -alias ${buildType} -keyalg RSA -keysize 2048 -validity 10000 -storepass ${storePassword} -keypass ${keyPassword} -dname "CN=${appId}, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown"`, 36 | ) 37 | 38 | addInFileAfter(gradleFile, `${buildType} {`, indentString(`\nsigningConfig signingConfigs.${buildType}`, 12)) 39 | 40 | // prettier-ignore 41 | addInFileAfter( 42 | gradleFile, 43 | 'signingConfigs {', 44 | indentString( 45 | '\n' + 46 | `${buildType} {\n` + 47 | ` storeFile file("./${keyStoreFile}")\n` + 48 | ` storePassword "${storePassword}"\n` + 49 | ` keyAlias "${buildType}"\n` + 50 | ` keyPassword "${keyPassword}"\n` + 51 | '}\n', 52 | 8 53 | ) 54 | ) 55 | } 56 | 57 | export const setupApkSigning = (appId, gradleFile = './android/app/build.gradle') => { 58 | // prettier-ignore 59 | addInFileBefore( 60 | './android/app/build.gradle', 61 | indentString('buildTypes {', 4), 62 | indentString( 63 | '\n'+ 64 | 'signingConfigs {\n' + 65 | '}\n', 66 | 4 67 | ) 68 | ) 69 | 70 | fs.mkdirp('./android/app/keyStores') 71 | generateKeystore(gradleFile, appId, 'debug') 72 | generateKeystore(gradleFile, appId, 'staging') 73 | generateKeystore(gradleFile, appId, 'release') 74 | 75 | // We want to commit the keystores to git. 76 | replaceInFile('./.gitignore', '*.keystore', '') 77 | } 78 | -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/debug/res/playstore-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/debug/res/playstore-icon.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/release/res/playstore-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/release/res/playstore-icon.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-ldpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-ldpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /src/reactNativeConfig/androidAppIcons/staging/res/playstore-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/androidAppIcons/staging/res/playstore-icon.png -------------------------------------------------------------------------------- /src/reactNativeConfig/index.js: -------------------------------------------------------------------------------- 1 | import { replaceInFile, addInFileAfter } from '~/common/replace' 2 | import executeCommand, { checkCommandsExist } from '~/common/executeCommand' 3 | import addNpmScript from '~/common/addNpmScript' 4 | import updateJson from '~/common/updateJson' 5 | import prompt from 'prompt-promise' 6 | import { copyFiles } from '~/common/copy' 7 | import path from 'path' 8 | import indentString from 'indent-string' 9 | 10 | import { findReactNativeProjectName, projectFileFromProjectName } from './reactNative' 11 | 12 | import { appNamePerEnvironment, iconsPerEnvironment, addPreProcessorEnvironments, bundleIdPerEnvironment, copyBuildConfiguration } from './xcodeProject' 13 | import { applicationIdSuffixPerEnvironment, appNameSuffixPerEnvironment, setupApkSigning } from './android' 14 | 15 | /* eslint-disable no-useless-concat, no-useless-escape */ 16 | 17 | export default async () => { 18 | console.log('Checking prerequisite installs') 19 | checkCommandsExist(['npm', 'keytool', 'fastlane']) 20 | console.log('Adding React Native Config') 21 | 22 | const bundleId = await prompt('bundleId (will overwrite any existing bundleId) keep it short e.g. com.zdev.something): ') 23 | const appName = await prompt('App Name (e.g. Expresso): ') 24 | 25 | const xcodeProjectName = findReactNativeProjectName() 26 | 27 | const projectFile = projectFileFromProjectName(xcodeProjectName) 28 | 29 | copyBuildConfiguration(projectFile, 'Release', 'Staging') 30 | 31 | addPreProcessorEnvironments(projectFile) 32 | 33 | bundleIdPerEnvironment(xcodeProjectName, bundleId) 34 | 35 | appNamePerEnvironment(xcodeProjectName, appName) 36 | 37 | iconsPerEnvironment(xcodeProjectName) 38 | 39 | executeCommand('npm install --save-dev react-native-schemes-manager') 40 | 41 | addNpmScript('postinstall', 'react-native-schemes-manager all') 42 | 43 | updateJson( 44 | { 45 | xcodeSchemes: { 46 | Release: ['Staging'], 47 | Debug: [], 48 | }, 49 | }, 50 | './package.json', 51 | ) 52 | 53 | // package-lock.json had to be removed to make this work. 54 | executeCommand('rm package-lock.json && npm install') 55 | 56 | replaceInFile(`./ios/${xcodeProjectName}/AppDelegate.m`, 'initialProperties:nil', 'initialProperties:@{@"environment" : ENVIRONMENT}') 57 | 58 | // prettier-ignore 59 | addInFileAfter( 60 | './android/app/build.gradle', 61 | 'import com.android.build.OutputFile', 62 | '\n\n' + 63 | 'project.ext.react = [\n' + 64 | ' bundleInStaging: true,\n' + 65 | ' devDisabledInStaging: true,\n' + 66 | ' bundleInRelease: true\n' + 67 | ']\n', 68 | ) 69 | 70 | addInFileAfter( 71 | './android/app/build.gradle', 72 | `proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 73 | }`, 74 | `\n staging { 75 | minifyEnabled enableProguardInReleaseBuilds 76 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 77 | }`, 78 | ) 79 | 80 | addInFileAfter( 81 | `./android/app/src/main/java/com/${xcodeProjectName}/MainActivity.java`, 82 | `return "${xcodeProjectName}"; 83 | }`, 84 | `\n @Override 85 | protected ReactActivityDelegate createReactActivityDelegate() { 86 | return new ReactActivityDelegate(this, getMainComponentName()) { 87 | @Nullable 88 | @Override 89 | protected Bundle getLaunchOptions() { 90 | Bundle initialProps = new Bundle(); 91 | initialProps.putString("environment", BuildConfig.BUILD_TYPE); 92 | return initialProps; 93 | } 94 | }; 95 | }`, 96 | ) 97 | 98 | // prettier-ignore 99 | addInFileAfter( 100 | `./android/app/src/main/java/com/${xcodeProjectName}/MainActivity.java`, 101 | `import com.facebook.react.ReactActivity;`, 102 | '\n' + 103 | 'import com.facebook.react.ReactActivityDelegate;\n' + 104 | 'import android.os.Bundle;\n' + 105 | 'import android.support.annotation.Nullable;\n' 106 | ) 107 | 108 | // prettier-ignore 109 | replaceInFile( 110 | './android/app/build.gradle', 111 | /applicationId \".*\"/, 112 | `applicationId "${bundleId}"`, 113 | ) 114 | 115 | // prettier-ignore 116 | addInFileAfter( 117 | './android/app/build.gradle', 118 | 'buildTypes {', 119 | indentString( 120 | '\n' + 121 | 'debug {\n' + 122 | '}', 123 | 8 124 | ) 125 | ) 126 | 127 | applicationIdSuffixPerEnvironment() 128 | appNameSuffixPerEnvironment(appName) 129 | 130 | copyFiles(path.join(__dirname, 'src/reactNativeConfig/androidAppIcons'), `./android/app/src/`) 131 | 132 | setupApkSigning(bundleId) 133 | } 134 | -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images":[ 3 | { 4 | "idiom":"iphone", 5 | "size":"20x20", 6 | "scale":"2x", 7 | "filename":"Icon-App-20x20@2x.png" 8 | }, 9 | { 10 | "idiom":"iphone", 11 | "size":"20x20", 12 | "scale":"3x", 13 | "filename":"Icon-App-20x20@3x.png" 14 | }, 15 | { 16 | "idiom":"iphone", 17 | "size":"29x29", 18 | "scale":"1x", 19 | "filename":"Icon-App-29x29@1x.png" 20 | }, 21 | { 22 | "idiom":"iphone", 23 | "size":"29x29", 24 | "scale":"2x", 25 | "filename":"Icon-App-29x29@2x.png" 26 | }, 27 | { 28 | "idiom":"iphone", 29 | "size":"29x29", 30 | "scale":"3x", 31 | "filename":"Icon-App-29x29@3x.png" 32 | }, 33 | { 34 | "idiom":"iphone", 35 | "size":"40x40", 36 | "scale":"1x", 37 | "filename":"Icon-App-40x40@1x.png" 38 | }, 39 | { 40 | "idiom":"iphone", 41 | "size":"40x40", 42 | "scale":"2x", 43 | "filename":"Icon-App-40x40@2x.png" 44 | }, 45 | { 46 | "idiom":"iphone", 47 | "size":"40x40", 48 | "scale":"3x", 49 | "filename":"Icon-App-40x40@3x.png" 50 | }, 51 | { 52 | "idiom":"iphone", 53 | "size":"57x57", 54 | "scale":"1x", 55 | "filename":"Icon-App-57x57@1x.png" 56 | }, 57 | { 58 | "idiom":"iphone", 59 | "size":"57x57", 60 | "scale":"2x", 61 | "filename":"Icon-App-57x57@2x.png" 62 | }, 63 | { 64 | "idiom":"iphone", 65 | "size":"60x60", 66 | "scale":"1x", 67 | "filename":"Icon-App-60x60@1x.png" 68 | }, 69 | { 70 | "idiom":"iphone", 71 | "size":"60x60", 72 | "scale":"2x", 73 | "filename":"Icon-App-60x60@2x.png" 74 | }, 75 | { 76 | "idiom":"iphone", 77 | "size":"60x60", 78 | "scale":"3x", 79 | "filename":"Icon-App-60x60@3x.png" 80 | }, 81 | { 82 | "idiom":"iphone", 83 | "size":"76x76", 84 | "scale":"1x", 85 | "filename":"Icon-App-76x76@1x.png" 86 | }, 87 | { 88 | "idiom":"ipad", 89 | "size":"20x20", 90 | "scale":"1x", 91 | "filename":"Icon-App-20x20@1x.png" 92 | }, 93 | { 94 | "idiom":"ipad", 95 | "size":"20x20", 96 | "scale":"2x", 97 | "filename":"Icon-App-20x20@2x.png" 98 | }, 99 | { 100 | "idiom":"ipad", 101 | "size":"29x29", 102 | "scale":"1x", 103 | "filename":"Icon-App-29x29@1x.png" 104 | }, 105 | { 106 | "idiom":"ipad", 107 | "size":"29x29", 108 | "scale":"2x", 109 | "filename":"Icon-App-29x29@2x.png" 110 | }, 111 | { 112 | "idiom":"ipad", 113 | "size":"40x40", 114 | "scale":"1x", 115 | "filename":"Icon-App-40x40@1x.png" 116 | }, 117 | { 118 | "idiom":"ipad", 119 | "size":"40x40", 120 | "scale":"2x", 121 | "filename":"Icon-App-40x40@2x.png" 122 | }, 123 | { 124 | "size" : "50x50", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-Small-50x50@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "50x50", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-Small-50x50@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "idiom":"ipad", 137 | "size":"72x72", 138 | "scale":"1x", 139 | "filename":"Icon-App-72x72@1x.png" 140 | }, 141 | { 142 | "idiom":"ipad", 143 | "size":"72x72", 144 | "scale":"2x", 145 | "filename":"Icon-App-72x72@2x.png" 146 | }, 147 | { 148 | "idiom":"ipad", 149 | "size":"76x76", 150 | "scale":"1x", 151 | "filename":"Icon-App-76x76@1x.png" 152 | }, 153 | { 154 | "idiom":"ipad", 155 | "size":"76x76", 156 | "scale":"2x", 157 | "filename":"Icon-App-76x76@2x.png" 158 | }, 159 | { 160 | "idiom":"ipad", 161 | "size":"76x76", 162 | "scale":"3x", 163 | "filename":"Icon-App-76x76@3x.png" 164 | }, 165 | { 166 | "idiom":"ipad", 167 | "size":"83.5x83.5", 168 | "scale":"2x", 169 | "filename":"Icon-App-83.5x83.5@2x.png" 170 | } 171 | ], 172 | "info":{ 173 | "version":1, 174 | "author":"makeappicon" 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-76x76@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Debug.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images":[ 3 | { 4 | "idiom":"iphone", 5 | "size":"20x20", 6 | "scale":"2x", 7 | "filename":"Icon-App-20x20@2x.png" 8 | }, 9 | { 10 | "idiom":"iphone", 11 | "size":"20x20", 12 | "scale":"3x", 13 | "filename":"Icon-App-20x20@3x.png" 14 | }, 15 | { 16 | "idiom":"iphone", 17 | "size":"29x29", 18 | "scale":"1x", 19 | "filename":"Icon-App-29x29@1x.png" 20 | }, 21 | { 22 | "idiom":"iphone", 23 | "size":"29x29", 24 | "scale":"2x", 25 | "filename":"Icon-App-29x29@2x.png" 26 | }, 27 | { 28 | "idiom":"iphone", 29 | "size":"29x29", 30 | "scale":"3x", 31 | "filename":"Icon-App-29x29@3x.png" 32 | }, 33 | { 34 | "idiom":"iphone", 35 | "size":"40x40", 36 | "scale":"1x", 37 | "filename":"Icon-App-40x40@1x.png" 38 | }, 39 | { 40 | "idiom":"iphone", 41 | "size":"40x40", 42 | "scale":"2x", 43 | "filename":"Icon-App-40x40@2x.png" 44 | }, 45 | { 46 | "idiom":"iphone", 47 | "size":"40x40", 48 | "scale":"3x", 49 | "filename":"Icon-App-40x40@3x.png" 50 | }, 51 | { 52 | "idiom":"iphone", 53 | "size":"57x57", 54 | "scale":"1x", 55 | "filename":"Icon-App-57x57@1x.png" 56 | }, 57 | { 58 | "idiom":"iphone", 59 | "size":"57x57", 60 | "scale":"2x", 61 | "filename":"Icon-App-57x57@2x.png" 62 | }, 63 | { 64 | "idiom":"iphone", 65 | "size":"60x60", 66 | "scale":"1x", 67 | "filename":"Icon-App-60x60@1x.png" 68 | }, 69 | { 70 | "idiom":"iphone", 71 | "size":"60x60", 72 | "scale":"2x", 73 | "filename":"Icon-App-60x60@2x.png" 74 | }, 75 | { 76 | "idiom":"iphone", 77 | "size":"60x60", 78 | "scale":"3x", 79 | "filename":"Icon-App-60x60@3x.png" 80 | }, 81 | { 82 | "idiom":"iphone", 83 | "size":"76x76", 84 | "scale":"1x", 85 | "filename":"Icon-App-76x76@1x.png" 86 | }, 87 | { 88 | "idiom":"ipad", 89 | "size":"20x20", 90 | "scale":"1x", 91 | "filename":"Icon-App-20x20@1x.png" 92 | }, 93 | { 94 | "idiom":"ipad", 95 | "size":"20x20", 96 | "scale":"2x", 97 | "filename":"Icon-App-20x20@2x.png" 98 | }, 99 | { 100 | "idiom":"ipad", 101 | "size":"29x29", 102 | "scale":"1x", 103 | "filename":"Icon-App-29x29@1x.png" 104 | }, 105 | { 106 | "idiom":"ipad", 107 | "size":"29x29", 108 | "scale":"2x", 109 | "filename":"Icon-App-29x29@2x.png" 110 | }, 111 | { 112 | "idiom":"ipad", 113 | "size":"40x40", 114 | "scale":"1x", 115 | "filename":"Icon-App-40x40@1x.png" 116 | }, 117 | { 118 | "idiom":"ipad", 119 | "size":"40x40", 120 | "scale":"2x", 121 | "filename":"Icon-App-40x40@2x.png" 122 | }, 123 | { 124 | "size" : "50x50", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-Small-50x50@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "50x50", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-Small-50x50@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "idiom":"ipad", 137 | "size":"72x72", 138 | "scale":"1x", 139 | "filename":"Icon-App-72x72@1x.png" 140 | }, 141 | { 142 | "idiom":"ipad", 143 | "size":"72x72", 144 | "scale":"2x", 145 | "filename":"Icon-App-72x72@2x.png" 146 | }, 147 | { 148 | "idiom":"ipad", 149 | "size":"76x76", 150 | "scale":"1x", 151 | "filename":"Icon-App-76x76@1x.png" 152 | }, 153 | { 154 | "idiom":"ipad", 155 | "size":"76x76", 156 | "scale":"2x", 157 | "filename":"Icon-App-76x76@2x.png" 158 | }, 159 | { 160 | "idiom":"ipad", 161 | "size":"76x76", 162 | "scale":"3x", 163 | "filename":"Icon-App-76x76@3x.png" 164 | }, 165 | { 166 | "idiom":"ipad", 167 | "size":"83.5x83.5", 168 | "scale":"2x", 169 | "filename":"Icon-App-83.5x83.5@2x.png" 170 | }, 171 | { 172 | "size" : "1024x1024", 173 | "idiom" : "ios-marketing", 174 | "filename" : "ItunesArtwork@2x.png", 175 | "scale" : "1x" 176 | } 177 | ], 178 | "info":{ 179 | "version":1, 180 | "author":"makeappicon" 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-76x76@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Release.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images":[ 3 | { 4 | "idiom":"iphone", 5 | "size":"20x20", 6 | "scale":"2x", 7 | "filename":"Icon-App-20x20@2x.png" 8 | }, 9 | { 10 | "idiom":"iphone", 11 | "size":"20x20", 12 | "scale":"3x", 13 | "filename":"Icon-App-20x20@3x.png" 14 | }, 15 | { 16 | "idiom":"iphone", 17 | "size":"29x29", 18 | "scale":"1x", 19 | "filename":"Icon-App-29x29@1x.png" 20 | }, 21 | { 22 | "idiom":"iphone", 23 | "size":"29x29", 24 | "scale":"2x", 25 | "filename":"Icon-App-29x29@2x.png" 26 | }, 27 | { 28 | "idiom":"iphone", 29 | "size":"29x29", 30 | "scale":"3x", 31 | "filename":"Icon-App-29x29@3x.png" 32 | }, 33 | { 34 | "idiom":"iphone", 35 | "size":"40x40", 36 | "scale":"1x", 37 | "filename":"Icon-App-40x40@1x.png" 38 | }, 39 | { 40 | "idiom":"iphone", 41 | "size":"40x40", 42 | "scale":"2x", 43 | "filename":"Icon-App-40x40@2x.png" 44 | }, 45 | { 46 | "idiom":"iphone", 47 | "size":"40x40", 48 | "scale":"3x", 49 | "filename":"Icon-App-40x40@3x.png" 50 | }, 51 | { 52 | "idiom":"iphone", 53 | "size":"57x57", 54 | "scale":"1x", 55 | "filename":"Icon-App-57x57@1x.png" 56 | }, 57 | { 58 | "idiom":"iphone", 59 | "size":"57x57", 60 | "scale":"2x", 61 | "filename":"Icon-App-57x57@2x.png" 62 | }, 63 | { 64 | "idiom":"iphone", 65 | "size":"60x60", 66 | "scale":"1x", 67 | "filename":"Icon-App-60x60@1x.png" 68 | }, 69 | { 70 | "idiom":"iphone", 71 | "size":"60x60", 72 | "scale":"2x", 73 | "filename":"Icon-App-60x60@2x.png" 74 | }, 75 | { 76 | "idiom":"iphone", 77 | "size":"60x60", 78 | "scale":"3x", 79 | "filename":"Icon-App-60x60@3x.png" 80 | }, 81 | { 82 | "idiom":"iphone", 83 | "size":"76x76", 84 | "scale":"1x", 85 | "filename":"Icon-App-76x76@1x.png" 86 | }, 87 | { 88 | "idiom":"ipad", 89 | "size":"20x20", 90 | "scale":"1x", 91 | "filename":"Icon-App-20x20@1x.png" 92 | }, 93 | { 94 | "idiom":"ipad", 95 | "size":"20x20", 96 | "scale":"2x", 97 | "filename":"Icon-App-20x20@2x.png" 98 | }, 99 | { 100 | "idiom":"ipad", 101 | "size":"29x29", 102 | "scale":"1x", 103 | "filename":"Icon-App-29x29@1x.png" 104 | }, 105 | { 106 | "idiom":"ipad", 107 | "size":"29x29", 108 | "scale":"2x", 109 | "filename":"Icon-App-29x29@2x.png" 110 | }, 111 | { 112 | "idiom":"ipad", 113 | "size":"40x40", 114 | "scale":"1x", 115 | "filename":"Icon-App-40x40@1x.png" 116 | }, 117 | { 118 | "idiom":"ipad", 119 | "size":"40x40", 120 | "scale":"2x", 121 | "filename":"Icon-App-40x40@2x.png" 122 | }, 123 | { 124 | "size" : "50x50", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-Small-50x50@1x.png", 127 | "scale" : "1x" 128 | }, 129 | { 130 | "size" : "50x50", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-Small-50x50@2x.png", 133 | "scale" : "2x" 134 | }, 135 | { 136 | "idiom":"ipad", 137 | "size":"72x72", 138 | "scale":"1x", 139 | "filename":"Icon-App-72x72@1x.png" 140 | }, 141 | { 142 | "idiom":"ipad", 143 | "size":"72x72", 144 | "scale":"2x", 145 | "filename":"Icon-App-72x72@2x.png" 146 | }, 147 | { 148 | "idiom":"ipad", 149 | "size":"76x76", 150 | "scale":"1x", 151 | "filename":"Icon-App-76x76@1x.png" 152 | }, 153 | { 154 | "idiom":"ipad", 155 | "size":"76x76", 156 | "scale":"2x", 157 | "filename":"Icon-App-76x76@2x.png" 158 | }, 159 | { 160 | "idiom":"ipad", 161 | "size":"76x76", 162 | "scale":"3x", 163 | "filename":"Icon-App-76x76@3x.png" 164 | }, 165 | { 166 | "idiom":"ipad", 167 | "size":"83.5x83.5", 168 | "scale":"2x", 169 | "filename":"Icon-App-83.5x83.5@2x.png" 170 | }, 171 | { 172 | "size" : "1024x1024", 173 | "idiom" : "ios-marketing", 174 | "filename" : "ItunesArtwork@2x.png", 175 | "scale" : "1x" 176 | } 177 | ], 178 | "info":{ 179 | "version":1, 180 | "author":"makeappicon" 181 | } 182 | } 183 | -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-57x57@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-57x57@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-57x57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-57x57@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-72x72@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-72x72@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-72x72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-72x72@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-76x76@3x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-Small-50x50@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-Small-50x50@1x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-Small-50x50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/Icon-Small-50x50@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/src/reactNativeConfig/iosAppIcons/AppIcon.Staging.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /src/reactNativeConfig/reactNative.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs' 2 | import _ from 'lodash' 3 | 4 | const XCODE_PROJECT_SUFFIX = '.xcodeproj' 5 | 6 | export const findReactNativeProjectName = () => { 7 | const files = fs.readdirSync('./ios') 8 | const xcodeProjectFile = _.find(files, f => f.endsWith(XCODE_PROJECT_SUFFIX)) 9 | return xcodeProjectFile.replace(XCODE_PROJECT_SUFFIX, '') 10 | } 11 | 12 | export const projectFileFromProjectName = xcodeProjectName => `ios/${xcodeProjectName}.xcodeproj/project.pbxproj` 13 | -------------------------------------------------------------------------------- /src/reactNativeConfig/xcodeProject.js: -------------------------------------------------------------------------------- 1 | import xcode from 'xcode' 2 | import _ from 'lodash' 3 | import fs from 'fs-extra' 4 | import { copyFiles } from '~/common/copy' 5 | import { arrayWrap } from '~/common/utils' 6 | import plist from 'plist' 7 | import path from 'path' 8 | 9 | import { projectFileFromProjectName } from './reactNative' 10 | 11 | const xcodeProjectFromFile = projectPath => xcode.project(projectPath).parseSync() 12 | 13 | const saveXcodeProject = (projectPath, xcodeProject) => fs.writeFileSync(projectPath, xcodeProject.writeSync()) 14 | 15 | const updateInfoPlist = (infoPlistFile, key, value) => { 16 | const data = plist.parse(fs.readFileSync(infoPlistFile, 'utf8')) 17 | fs.writeFileSync(infoPlistFile, plist.build({ ...data, [key]: value })) 18 | } 19 | 20 | const getBuildConfigurations = projectPath => { 21 | const xcodeProject = xcodeProjectFromFile(projectPath) 22 | return _.chain(xcodeProject.pbxXCBuildConfigurationSection()) 23 | .map(buildConfiguration => buildConfiguration.name) 24 | .uniq() 25 | .compact() 26 | .value() 27 | } 28 | 29 | const findBuildConfigs = (xcodeProject, buildConfiguration) => _.filter(xcodeProject.pbxXCBuildConfigurationSection(), config => config.name === buildConfiguration) 30 | 31 | const findProjectBuildConfig = (xcodeProject, buildConfiguration) => 32 | _.find(findBuildConfigs(xcodeProject, buildConfiguration), config => !_.has(config, 'buildSettings.PRODUCT_NAME')) 33 | 34 | const findAppBuildConfig = (xcodeProject, buildConfiguration) => 35 | _.find(findBuildConfigs(xcodeProject, buildConfiguration), config => { 36 | const infoPlistFile = _.get(config, 'buildSettings.INFOPLIST_FILE') 37 | return !_.includes(infoPlistFile, 'tvOS') && !_.includes(infoPlistFile, 'Tests/') && !_.has(config, 'buildSettings.GCC_PREPROCESSOR_DEFINITIONS') 38 | }) 39 | 40 | export const appNamePerEnvironment = (projectName, appNamePrefix) => { 41 | const projectPath = projectFileFromProjectName(projectName) 42 | console.log(`\nAdding App Name per environment ${projectPath}\n`) 43 | 44 | const xcodeProject = xcodeProjectFromFile(projectPath) 45 | const buildConfigurations = getBuildConfigurations(projectPath) 46 | _.forEach(buildConfigurations, buildConfiguration => { 47 | const projectBuildConfig = findProjectBuildConfig(xcodeProject, buildConfiguration) 48 | const appNameSuffix = buildConfiguration === 'Release' ? '' : ` ${buildConfiguration}` 49 | const appName = `${appNamePrefix}${appNameSuffix}` 50 | console.log(`\nSetting up a App Name for ${buildConfiguration}: ${appName}\n`) 51 | projectBuildConfig.buildSettings.APP_NAME = `"${appName}"` 52 | }) 53 | saveXcodeProject(projectPath, xcodeProject) 54 | updateInfoPlist(`ios/${projectName}/Info.plist`, 'CFBundleDisplayName', '$(APP_NAME)') 55 | } 56 | 57 | export const bundleIdPerEnvironment = (projectName, bundleIdPrefix) => { 58 | const projectPath = projectFileFromProjectName(projectName) 59 | console.log(`\nSetting up a bundle id per environment ${projectPath}\n`) 60 | 61 | const xcodeProject = xcodeProjectFromFile(projectPath) 62 | const buildConfigurations = getBuildConfigurations(projectPath) 63 | _.forEach(buildConfigurations, buildConfiguration => { 64 | const buildConfigurationSuffix = buildConfiguration === 'Release' ? '' : `.${_.toLower(buildConfiguration)}` 65 | const projectBuildConfig = findProjectBuildConfig(xcodeProject, buildConfiguration) 66 | const bundleId = `${bundleIdPrefix}${buildConfigurationSuffix}` 67 | console.log(`\nSetting up a bundle id for ${buildConfiguration}: ${bundleId}\n`) 68 | projectBuildConfig.buildSettings.PRODUCT_BUNDLE_IDENTIFIER = bundleId 69 | }) 70 | saveXcodeProject(projectPath, xcodeProject) 71 | updateInfoPlist(`ios/${projectName}/Info.plist`, 'CFBundleIdentifier', '$(PRODUCT_BUNDLE_IDENTIFIER)') 72 | } 73 | 74 | export const addPreProcessorEnvironments = projectPath => { 75 | console.log(`\nAdding Preprocessor ENVIRONMENT variables in ${projectPath}\n`) 76 | 77 | const xcodeProject = xcodeProjectFromFile(projectPath) 78 | const buildConfigurations = getBuildConfigurations(projectPath) 79 | _.forEach(buildConfigurations, buildConfiguration => { 80 | const projectBuildConfig = findProjectBuildConfig(xcodeProject, buildConfiguration) 81 | const environmentDefiniton = `"ENVIRONMENT=\\\\@\\\\\\"${_.toUpper(buildConfiguration)}\\\\\\""` 82 | const gccPreprocessorDefinitions = [environmentDefiniton, ...arrayWrap(projectBuildConfig.buildSettings.GCC_PREPROCESSOR_DEFINITIONS)] 83 | projectBuildConfig.buildSettings.GCC_PREPROCESSOR_DEFINITIONS = gccPreprocessorDefinitions 84 | }) 85 | saveXcodeProject(projectPath, xcodeProject) 86 | } 87 | 88 | export const iconsPerEnvironment = projectName => { 89 | const projectPath = projectFileFromProjectName(projectName) 90 | console.log(`\nAdding App Icon per environment\n`) 91 | copyFiles(path.join(__dirname, 'src/reactNativeConfig/iosAppIcons'), `ios/${projectName}/Images.xcassets/`) 92 | fs.remove(`ios/${projectName}/Images.xcassets/AppIcon.appiconset`) 93 | const xcodeProject = xcodeProjectFromFile(projectPath) 94 | const buildConfigurations = getBuildConfigurations(projectPath) 95 | _.forEach(buildConfigurations, buildConfiguration => { 96 | const appBuildConfig = findAppBuildConfig(xcodeProject, buildConfiguration) 97 | appBuildConfig.buildSettings.ASSETCATALOG_COMPILER_APPICON_NAME = `AppIcon.${buildConfiguration}` 98 | }) 99 | saveXcodeProject(projectPath, xcodeProject) 100 | } 101 | 102 | export const copyBuildConfiguration = (projectPath, existingBuildConfigName, newBuildConfigurationName) => { 103 | console.log(`\nCopying build configuration: ${existingBuildConfigName} to ${newBuildConfigurationName} in ${projectPath}\n`) 104 | const xcodeProject = xcodeProjectFromFile(projectPath) 105 | 106 | const buildConfigurationsToCopy = _.pickBy(xcodeProject.pbxXCBuildConfigurationSection(), buildConfiguration => buildConfiguration.name === existingBuildConfigName) 107 | 108 | _.forEach(buildConfigurationsToCopy, (buildConfigurationToCopy, key) => { 109 | const newBuildConfigUuid = xcodeProject.generateUuid() 110 | xcodeProject.pbxXCBuildConfigurationSection()[newBuildConfigUuid] = _.cloneDeep(buildConfigurationToCopy) 111 | xcodeProject.pbxXCBuildConfigurationSection()[newBuildConfigUuid].name = newBuildConfigurationName 112 | xcodeProject.pbxXCBuildConfigurationSection()[`${newBuildConfigUuid}_comment`] = newBuildConfigurationName 113 | 114 | const xcConfigListKey = _.findKey(xcodeProject.pbxXCConfigurationList(), xcConfigList => _.includes(_.map(xcConfigList.buildConfigurations, 'value'), key)) 115 | 116 | xcodeProject.pbxXCConfigurationList()[xcConfigListKey].buildConfigurations.push({ value: newBuildConfigUuid, comment: newBuildConfigurationName }) 117 | }) 118 | 119 | saveXcodeProject(projectPath, xcodeProject) 120 | } 121 | -------------------------------------------------------------------------------- /src/reactNativeInit/index.js: -------------------------------------------------------------------------------- 1 | import executeCommand, { checkCommandsExist } from '~/common/executeCommand' 2 | import prompt from 'prompt-promise' 3 | 4 | export default async argv => { 5 | console.log('Checking prerequisite installs') 6 | checkCommandsExist(['react-native', 'react-native-rename']) 7 | console.log('Initializing React Native codebase') 8 | 9 | const bundleId = await prompt('bundleId (will overwrite any existing bundleId) e.g. com.zdev.myapp): ') 10 | const appName = await prompt('App Name (e.g. Expresso): ') 11 | const reactNativeVersion = argv.reactNativeVersion || '0.48.4' 12 | 13 | executeCommand(`react-native init --version react-native@${reactNativeVersion} RNScaffold`) 14 | 15 | executeCommand(`(cd RNScaffold && react-native-rename ${appName} -b ${bundleId})`) 16 | executeCommand(`mv RNScaffold ${appName}`) 17 | } 18 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/z-dev/rn-scaffold/e3022fe2dd331dbed02fb9fa52ea36ea01cd0ecf/test/test.js --------------------------------------------------------------------------------