Node: Problems & Solutions - Part 3 of 3 (FINAL) (course completed and app deployed)

ok this is my FINAL post on the Node course, having completed and deployed. I am using windows 10, vscode and my package.json is shown below. (I used latest packages, from Jan-mar 2022). (scroll to end for github repo with all code).

Part 1 had some issues and solutions from first half of course.
Part 2 had issues and solutions from second half of course.
This post is just about the deployment. I had no problems, but I have deployed a few apps to github and heroku before and had run into some issues so I wanted to cover these briefly here (I have separate posts on these). Also, I didnt like having to remember to have jwtPrivateKey in environment and I also didnt like having the user name and password as part of the connection string, so I made a few changes to config.js and db.js which I will show here.

GitHub - In this course it mentions “master” branch. Since 2020 I think this has been called “main” so where it says to use “master”, use “main”. Even the instructions on Github tell you to run git branch -M main which names your top level branch “main”. Also, Heroku site mentions to rename your top level branch main. If you didnt, dont worry. you can rename even after pushing to Github. If you get in a mess with Github (as I did) again, dont worry, there are solutions. Finally, if you decide (and you should) to put your confidential info into env variables in an .env file, then make sure you add .env to your .gitignore file. “All this and more” in another post I have on Github.

Heroku - similar to Github, the course tells you to push to master. Change both to main. You will be glad later that you did. On Heroku under settings, Config, you can add your env variables easily (or you could use command line heroku config: set name = value). Remember, you MUST put .env into .gitignore so your confidential info is NOT copied to your repo and pushed to github/heroku. Heroku has you covered. Use this exact same env names in Settings/config and your code will work just fine. If you have NODE_ENV in your .env file then locally you can put NODE_ENV = “development” and on heroku put = “production”.

Ok, as mentioned I have a post on Github and I have another on Heroku.

Now to the “issues” with deployment. It all worked fine as per Moshs instructions. I had done a few deploys to Github and Heroku so this went smoothly for me except i had a typo on the long heroku config:set vidly_db=mongodb+srv line so the app kept failing till I found that. However, I did not like two things about the deployment and these were:
(1) having to remember to set env variable for jwtPrivateKey or get an error. That was annoying everytime I closed hyper and restarted. More of an issue generally than the deploy but I wanted to “fix” it for the deploy.
(2) that long connection string line that I had a typo in that includes the username and password. For me, thats a no. Not just because of the potential typo but confidential info should be in env variables (and yes I know it was creating an env on heroku) but the code leaves you guessing what is vidly_db supposed to be.

Here are my “solutions”, but please note the app works fine without these.
(1) create an .env file and put your confidential key in here:
vidly_jetPrivateKey=“1234”
NOTE: add .env to your .gitignore so this does NOT get copied to your repo.
Now, to get the env variable in the code, I use package DOTENV. So, npm i dotenv
I changed config.js as shown below. With dotenv you can “create” env variables from whats in your .env file.

require("dotenv").config();
const vidKey = process.env.vidly_jwtPrivateKey;

module.exports = function () {
  if (!vidKey) {
    throw new Error("FATAL ERROR: jwtPrivateKey is not defined");
  }
};

(2) Again, I wanted to use env file to store the username and password - confidential info. For simplicity I added the NODE_ENV variable also. (There is probably a better way to separate what should go in config files vs env files and Mosh chose to use package config so I worked with it.) So I added variables to .env and it now looks like this:
.env

NODE_ENV="development"
vidly_jwtPrivateKey="1234"
db_usr="vidly-user"
db_key="vi1234"

Then, db.js is where the connection string is being set (for local db) and relies on the heroku config to set the vidly_db for the remote/cloud db. So, I changed the code for db.js to use both config and dotenv and create the connection string for remote (production). (Ideally, I think that connection string belongs in prod.json in config folder so that it can be changed easily without changing code.)

db.js

const winston = require("winston");
const mongoose = require("mongoose");
const config = require("config");
require("dotenv").config();

module.exports = function () {
  let db = config.get("db"); // use for local
  // cloud requires server credentials (.env)
  const envN = process.env.NODE_ENV;
  if (envN === "production") {
    const db_usr = process.env.db_usr;
    const db_key = process.env.db_key;
    db =
      "mongodb+srv://" +
      db_usr +
      ":" +
      db_key +
      "@cluster0.57qzj.mongodb.net/vidly?retryWrites=true&w=majority";
    console.log("db: ", db);
  }

  mongoose
    .connect(db, { useNewUrlParser: true })
    .then(() => winston.info(`Connected to Mongodb: ${db} ...`));
};

With that done, you dont need to heroku config that long connection string with embedded username and password. And in Heroku, Settings, Reveal Config Vars you need the following:
db_key : vi1234 (or whatever your user pw is)
db_usr : vidly_user (or whatever your user name is)
NODE_ENV: production
jwt_PrivateKey: 1234 (or whatever you chose for your private key)

Basically, these Heroku config vars should be identical names to your .env variable names. The value for NODE_ENV could be “deployment” in the .env (locally) but production on heroku. Note that case is important.

If you make these changes then you need to push to heroku and if you have created a github repo then you also need to push to github … run these lines individually in terminal.

git add .
get commit -m "mod to config.js and db.js to use dotenv"
git push heroku main   // push to heroku
git push -u origin main  // push to github

And thats it. With these changes, put your heroku url into your browser and you should see “Welcome to Vidly!” and in Postman you can repeat the checks and all works fine.

Hope this helps someone. Look out for my other posts on Github/Heroku.

Another brilliant course from Mosh. Happy Coding.

pS. nearly forgot. below is my package.json. My github repo is: Github repo for Vidly

package.json

{
  "name": "vidly",
  "version": "1.1.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "jest --watchAll --verbose --maxWorkers=1",
    "start": "node index.js"
  },
  "engines": {
    "node": "16.14.0"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "bcrypt": "^5.0.1",
    "compression": "^1.7.4",
    "config": "^3.3.7",
    "dotenv": "^16.0.0",
    "express": "^4.17.3",
    "express-async-errors": "^3.1.1",
    "fawn": "^2.1.5",
    "helmet": "^5.0.2",
    "joi": "^17.6.0",
    "joi-objectid": "^4.0.2",
    "jsonwebtoken": "^8.5.1",
    "lodash": "^4.17.21",
    "moment": "^2.29.1",
    "mongoose": "^6.2.4",
    "winston": "^3.6.0",
    "winston-mongodb": "^5.0.7"
  },
  "devDependencies": {
    "jest": "^27.5.1",
    "supertest": "^6.2.2"
  }
}