Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DATA-AND-IDENTITY-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,12 @@ The key difference: `req` is a **separate object for every request**, so each re

If you see `global.user_id` in older lesson code and `req.user.id` in later code, that is exactly the transition described here. When you reach Lesson 8, expect to search your controllers for `global.user_id` and replace it.

## **Part 3 — One Database Becomes Three**
## **Part 3 — One Database Becomes Several**

Once your data lives in a database, you are actually juggling more than one: a **development** database you work in by hand, a separate **test** database the automated tests delete and re-create, and later a **production** database in the cloud for real users. Keeping them straight is one of the most common sources of confusion in the course.
Once your data lives in a database, you are actually juggling more than one. In Lesson 5, there is a SQL practice database for `sqlcommand` and Assignment 5a, plus the task app development database. There is also a separate **test** database the automated tests delete and re-create, and later a **production** database in the cloud for real users. Keeping them straight is one of the most common sources of confusion in the course.

The full explanation, which connection string is which, why test must be separate, and what you must never run against production, lives in the [Environment Variables and Secrets guide](./ENVIRONMENT-VARIABLES-GUIDE.md).

## **The One-Paragraph Summary**

Your data starts in memory (Lessons 1–4), moves to a local PostgreSQL database you query with raw SQL (Lesson 5), then with Prisma (Lessons 6–7), and finally to a cloud database when you deploy (Lesson 10). Your app's sense of "who is logged in" starts as a single global variable (Lessons 4–7) and becomes real per-request authentication with JWTs and cookies in Lesson 8. Along the way you maintain three separate databases, development, test, and production, and most mysterious bugs come down to being connected to a different one than you thought.
Your data starts in memory (Lessons 1–4), moves to local PostgreSQL databases you query with raw SQL (Lesson 5), then with Prisma (Lessons 6–7), and finally to a cloud database when you deploy (Lesson 10). Your app's sense of "who is logged in" starts as a single global variable (Lessons 4–7) and becomes real per-request authentication with JWTs and cookies in Lesson 8. Along the way you maintain separate databases for practice data, development, testing, and production, and most mysterious bugs come down to being connected to a different one than you thought.
8 changes: 5 additions & 3 deletions ENVIRONMENT-VARIABLES-GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ The value is not written in your code. It comes from the environment, which mean
In development, the easiest way to set environment variables is a `.env` file in the root of your project. It is a plain text file where each line is a `NAME=value` pair:

```bash
DATABASE_URL=postgresql://user:password@localhost:5432/node_dev
TEST_DATABASE_URL=postgresql://user:password@localhost:5432/node_test
DB_URL=<connection string for the SQL practice database>
DATABASE_URL=<connection string for the task app development database>
TEST_DATABASE_URL=<connection string for the task app test database>
```

The [`dotenv`](https://www.npmjs.com/package/dotenv) package reads that file and copies each value into `process.env` when your app starts. That is why you install `dotenv` and call it near the top of your database connection file, before you read any values:
Expand Down Expand Up @@ -52,7 +53,8 @@ If a secret is ever committed by accident, treat it as compromised: rotate (chan

This is one of the most common sources of confusion in the course, so name it clearly. You are juggling more than one database connection string:

- **`DATABASE_URL`** — your **development** database, the one you work in by hand. Your Postman experiments and everyday data live here.
- **`DB_URL`** — the SQL practice database used by `sqlcommand`, `load-db.js`, and Assignment 5a. This database has the sample business tables such as customers, orders, products, and line items.
- **`DATABASE_URL`** — your task app **development** database, the one you use with Postman and everyday app data. This database has the app tables such as users and tasks.
- **`TEST_DATABASE_URL`** — a **separate test** database used only by the automated tests. The tests delete and re-create data freely, so it **must** point at a different database than your development one. If a test ever wipes data you cared about, this is usually why.
- **A production database** — added in the deployment assignment (Lesson 10). It lives in the cloud and serves real users. Be extremely careful with it. Commands that reset a database, like `npx prisma migrate reset`, must never be run against production.

Expand Down
27 changes: 20 additions & 7 deletions assignments/05-intro-to-sql-and-postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Start `sqlcommand` the same way you did in the lesson. For each task below, firs

It may help to keep two terminal sessions open in VSCode: one for `sqlcommand`, and one for running the homework tests.

Create a file named `assignment5-sql.txt` inside the `assignment5` directory. Each line in this file should be one SQL command, as described in the tasks. Lines that begin with `#` are treated as comments. As you add SQL statements to this file, test your work with:
Create a file named `assignment5-sql.txt` inside the `assignment5` directory. Each line in this file should be one SQL command, as described in the tasks. Lines that begin with `#` are treated as comments. Assignment 5a uses the sample SQL practice database from the lesson, so `DB_URL` must be set in your `.env` file. As you add SQL statements to this file, test your work with:

**💡 Tip:** When typing SQL commands in the `sqlcommand` terminal, add a space at the end of each line. Without trailing spaces, lines get concatenated together (e.g., `GROUP BY orders.order_idORDER BY` becomes invalid SQL).

Expand All @@ -27,7 +27,7 @@ The [SQL section of W3Schools](https://www.w3schools.com/sql/default.asp) is a g

Inside `sqlcommand`, practice several kinds of SQL statements: SELECT, INSERT, UPDATE, DELETE, BEGIN, COMMIT, and ROLLBACK. Also practice statements that use JOIN, GROUP BY, ORDER BY, HAVING, SUM, COUNT, and subqueries.

Keep practicing until the SQL feels less mysterious. Remember that you can reload the database if you need to reset your data. Then move on to the tasks below.
Keep practicing until the SQL feels less mysterious. Remember that you can reload the sample database with `node load-db.js` if you need to reset your data. Then move on to the tasks below.

**Note:** These tasks require SQL statements that are somewhat complicated. Implement the statements incrementally — get one part working, then add more clauses, until the full query works correctly. If you run into problems, ask for assistance from a mentor or via the Slack channel. If SQL is new to you, take your time with this section.

Expand Down Expand Up @@ -122,11 +122,23 @@ In this assignment, you will update your existing Express application so it uses
**Prologue:**
Right now, your app uses globals to store users and each user's tasks. For this assignment, remove all use of `global.users` and `global.tasks`. Read from and write to the database instead. The REST calls your application supports should still work the same way, so your Postman tests do not need to change.

For the big picture of how storage and login identity change across the course, see the [Data and Identity guide](../DATA-AND-IDENTITY-GUIDE.md).

## A Quick Word About Environment Variables and Secrets

Starting with this assignment, your app needs to know how to reach your database. That information includes a password, so it does not belong in your code. The standard solution is to keep it in an **environment variable**, loaded from a `.env` file that you never commit to git.

You set up your databases and your `.env` file back in Week 0, and this assignment assumes both exist. If you need a refresher on what environment variables are, how `.env` and `dotenv` work, and why you keep separate development and test databases, read the [Environment Variables and Secrets guide](https://github.com/Code-the-Dream-School/node-essentials/blob/e751ad5007be66a9a562d48d8223a081bd9c3cd3/ENVIRONMENT-VARIABLES-GUIDE.md) before continuing.
You set up your local PostgreSQL databases and your `.env` file back in Assignment 0, and this assignment assumes they already exist. Your `.env` file should contain connection strings for those databases. The variable names are:

```bash
DB_URL=<connection string for the SQL practice database>
DATABASE_URL=<connection string for the task app development database>
```

- `DB_URL` is used by `sqlcommand`, `load-db.js`, and Assignment 5a. This database contains the sample business tables such as customers, orders, products, and line items.
- `DATABASE_URL` is used by your Express app in Assignment 5b. This database contains the task app tables such as users and tasks.

If you need a refresher on what environment variables are, how `.env` and `dotenv` work, and why you keep separate development and test databases, read the [Environment Variables and Secrets guide](https://github.com/Code-the-Dream-School/node-essentials/blob/e751ad5007be66a9a562d48d8223a081bd9c3cd3/ENVIRONMENT-VARIABLES-GUIDE.md) before continuing.

## Prerequisites
- Completed previous lessons with a working Express application
Expand Down Expand Up @@ -160,7 +172,8 @@ For Mac:

```bash
psql --version # check version
brew services start postgresql@14 # You might have 15 or some different version
brew services list | grep postgresql # find the installed service name
brew services start postgresql@17 # replace postgresql@17 with the service name from the previous command
```

For Linux:
Expand All @@ -169,7 +182,7 @@ For Linux:
sudo service start postgresql
```

For Windows, you open the Windows Services panel and start the postgresql service if it is not running.
For Windows, open the Windows Services panel and start the PostgreSQL service if it is not running.

Remember these steps. If your app suddenly stops working, one possible cause is that the database service is not running.

Expand Down Expand Up @@ -258,7 +271,7 @@ await pool.end();

Without this, your Node process may hang on exit. You want the app to release all database connections.

#### b. Modify app.js: Health Check
#### c. Modify app.js: Health Check

Modify the health check endpoint to verify database connectivity:

Expand All @@ -273,7 +286,7 @@ app.get("/health", async (req, res) => {
});
```

#### c. Modify Your Error Handler
#### d. Modify Your Error Handler

Add the following line to the top of your error handler middleware:

Expand Down
2 changes: 2 additions & 0 deletions assignments/06-intro-to-prisma.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ Create an `assignment6` branch before you make new changes. This branch should b
**Prologue:**
Right now, your app uses raw SQL queries with the `pg` library. In this assignment, replace those raw SQL queries with Prisma ORM methods. Keep the same functionality, including password hashing and global user_id storage. The REST calls your application supports should still work the same way, so your Postman tests do not need to change.

For the big picture of how storage and login identity change across the course, see the [Data and Identity guide](../DATA-AND-IDENTITY-GUIDE.md).

## Prerequisites
- Completed Assignment 5 with a working PostgreSQL application
- Basic understanding of database concepts and SQL
Expand Down
2 changes: 2 additions & 0 deletions assignments/08-authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Otherwise it returns a 401 (unauthorized).

Your app currently uses a global user id to simulate logon and access control. In this assignment, you will remove that approach.

For the big picture of how storage and login identity change across the course, see the [Data and Identity guide](../DATA-AND-IDENTITY-GUIDE.md).

## **What do we Need in the JWT?**

> **📚 Concept Review**: Before implementing JWT tokens, make sure you understand what they are and how they work.
Expand Down
2 changes: 2 additions & 0 deletions lessons/04-tasks-validations.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ global.user_id = null;

That temporary setup lets you practice the backend patterns before the app moves to PostgreSQL and Prisma later.

For the big picture of how storage and login identity change across the course, see the [Data and Identity guide](../DATA-AND-IDENTITY-GUIDE.md).

## **4.2 Authentication and Authorization**

Authentication and authorization are related, but they are not the same.
Expand Down
2 changes: 1 addition & 1 deletion lessons/05-intro-to-sql-and-postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ Now that you understand what SQL does, it is time to use it from your app. You w

### **Configuring the Connection**

Database connections require a connection string, which is a URL. You created several connection strings during Assignment 0, and they are stored in your `.env` file. The connection string includes the host, database name, SSL mode, user ID, and password. The password must stay secret, so it belongs in `.env`, never in your source code. Make sure `.env` is listed in `.gitignore`. You do not use SSL for the local connection, but you will use SSL for the cloud database.
Database connections require a connection string, which is a URL. You created several local PostgreSQL connection strings during Assignment 0, and they are stored in your `.env` file. The connection string includes the host, database name, user ID, and sometimes a password or connection options. Any password must stay secret, so it belongs in `.env`, never in your source code. Make sure `.env` is listed in `.gitignore`. In Lesson 10, you will use Neon connection strings for deployment.

In your app, you want to centralize database connection management for two reasons:

Expand Down
2 changes: 1 addition & 1 deletion lessons/10-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ local Node app -> Neon database -> Render back end -> deployed front end config

First, you will make sure your local app can talk to the cloud database. Then you will deploy the back end to Render and give Render the environment variables it needs. After that, you will point the provided front end at the deployed back end. Finally, you will test the deployed application with Postman and the front end.

1. You need a cloud-hosted database. An application in the cloud cannot reach your local database because your laptop does not have a public database address. You will use neon.tech. You will create a free account and a database. When you create the database, you will get a URL that includes the database password.
1. You need a cloud-hosted database. An application in the cloud cannot reach your local database because your laptop does not have a public database address. You will use Neon. You will create a free account and a database. When you create the database, you will get a URL that includes the database password.

2. You will point your current Node application at the Neon database. This is a change to your `.env` file. Remember that the URL includes a password. The `.env` file is the place for that secret.

Expand Down