Your shop reads its products from shop.db. Now clients can add one: they send a POST to /products, the same path as the list, with the new product in the JSON body. Your route saves it with an INSERT statement.
Here is an INSERT on another table, a list of newsletter subscribers:
const result = db.prepare("INSERT INTO subscribers (email) VALUES (?)").run("sam@example.com");
console.log(result.lastInsertRowid); // the id the database chose for the new row
Three things matter. Each ? takes one value, in order, so whatever text the client sends stays a value and never becomes SQL. You leave the id out: the database picks the next free number, and result.lastInsertRowid tells you which. And there is no separate step to save: each statement is committed, which means saved for good, the moment .run finishes.
Starting from the shop's 8 products, your code must answer:
POST /products {"name": "Vase", "price": 18, "category": "home"} → 201 {"id": 9}
GET /products/9 → 200 {"id": 9, "name": "Vase", "price": 18, "category": "home", "stock": 0}
POST /products {"name": "Candle", "price": 6} → 201 {"id": 10}
GET /products?max_price=6 → 200 [{"id": 4, "name": "Pen", …}, {"id": 10, "name": "Candle", "price": 6, "category": null, "stock": 0}]
Your task: add the route POST /products. Read the body, insert the name, the price and the category (null if it is missing) with ? placeholders, and answer the new id with the status 201.
Assignment
Follow the Coding Tutorial to add the POST /products route, which saves a new product in the database.
Hint
The Candle has no category: data.category is undefined, and the database can't store that. Put null in its place: it is stored as NULL. Run the INSERT with .run, not .all: it gives back the object that has lastInsertRowid.
Free plan: 30 tutor messages. PRO is unlimited.
