Prepare Expo project with bash script to setup TypeScript ESLint Prettier
Tags: expo, bash, boilerplate, eslint
Published: 2022-07-02 14:20:40

In [this post](https://dev.to/dimaportenko/expo-typescript-eslint-prettier-initial-setup-54d3) I shared my step by step way to setup new expo project generally required to any project I would like to create. But after passed this instructions several times I found it very annoying and wasting my time. So I decided to write a script which will do all steps in one go. 

Let's create directory and script file
```bash
mkdir -p automation/bin
cd automation/bin
touch quickstart
```

So `quickstart` will be our executable, continue with write our script in this file. 

```bash
#!/usr/bin/env bash
```
This basically means that executable will be run by `bash`. 

I would like to run command with project name as param 
```bash
quickstart your-project-name-param
```

And I like to exit script if project name wasn't provided.
```bash
if [ -n "$1" ]; then
  echo $1
else
  echo "Error! Please enter project name!" 1>&2
  exit 1
fi
```
`$1` is first script param. And now we can create expo project with typescript template 
```bash
expo init -t expo-template-blank-typescript $1
```
Then move to the project directory and install dependencies
```bash
DIR="$(pwd)"
cd "$DIR/$1"

yarn add -D eslint prettier @react-native-community/eslint-config @typescript-eslint/eslint-plugin eslint-config-prettier
```

Create and fill `.eslintrc.js`
```bash
cat > .eslintrc.js <<EOF
module.exports = {
  extends: ['@react-native-community', "eslint-config-prettier"],
}
EOF
```

Update json files is easier to do inside the nodejs script `automation/patch-json.js`. 
```javascript
const fs = require('fs');

const args = process.argv.slice(2);
const getFilepath = (filename) => `${args[0]}/${filename}`
// console.log(args)

let fileName = getFilepath('tsconfig.json');
let file = require(fileName);

file.compilerOptions.module = "es6";

fs.writeFile(fileName, JSON.stringify(file), function writeJSON(err) {
  if (err) return console.log(err);
  console.log(JSON.stringify(file));
  console.log('writing to ' + fileName);
});

fileName = getFilepath('package.json');
file = require(fileName);

if (file.resolutions) {
  file.resolutions["@types/react"] = "^17"
} else {
  file.resolutions = {
    "@types/react": "^17"
  }
}

fs.writeFile(fileName, JSON.stringify(file), function writeJSON(err) {
  if (err) return console.log(err);
  console.log(JSON.stringify(file));
  console.log('writing to ' + fileName);
});
```

And we can run this node script like this
```bash
SCRIPTS_DIR="$(dirname -- "${BASH_SOURCE[0]}")/.."
node "$SCRIPTS_DIR/patch-json.js" "$DIR/$1"
```
`SCRIPTS_DIR` - directory where our `patch-json.js` script located. `"$DIR/$1"` - path of our newly created project.

Since I'm using WebStorm I would like to update `.gitignore`
```bash
echo ".idea" >> ".gitignore"
```

Apply all my rules with `prettier` 
```bash
./node_modules/prettier/bin-prettier.js --write .
```

And commit changes to the git
```bash
git add .
git commit -m 'expostart script updates'
```

And the final step - to be able run the command from any directory I need to add my `bin` directory to the terminal PATH varilble. I'm using [zsh](https://www.zsh.org/) so I'll put following to the `~/.zshrc` 
```bash
export PATH=$PATH:$HOME/scripts/expo/bin
```
Don't forget to source config before use
```bash
source ~/.zshrc
```

Now you can create new project with following command 
```bash
quickstart your-project-name
```

You can find full script in the [repository](https://github.com/dimaportenko/expostart-script).