Welcome back! In the last lesson, you learned how to make your cooking assistant more accessible by generating audio instructions using TypeScript and Express. Now, we are going to make your API even more useful and interactive by adding two new features: the ability to list all available ingredients and to let users submit reviews for recipes.
These features are important for any smart cooking app. Listing ingredients helps users see what’s available or filter recipes, while reviews allow users to share feedback and help others find the best recipes. By the end of this lesson, you will know how to build and test these endpoints in Express using TypeScript and Prisma.
Before we dive in, let’s quickly remind ourselves how endpoints work in Express with TypeScript. In Express, an endpoint is a function that runs when a user visits a certain URL. You define endpoints using methods like router.get or router.post, and you can specify which HTTP methods (such as GET or POST) the endpoint should accept.
For example, here’s a simple GET endpoint using Express Router:
router.get("/hello", ...)sets up the endpoint at/helloand only allowsGETrequests.- The function receives the request (
req) and response (res) objects. res.json(...)sends a JSON response to the client.
In this lesson, you’ll use similar patterns to build your new endpoints.
Let’s start by creating an endpoint that lists all unique ingredients in your database. This will be a GET endpoint, which means users will request data from it.
First, you need to define a new route for your endpoint. In your Express app, you can use a router. Here’s how you define the route using Express Router and TypeScript:
recipes.get("/ingredients", ...)sets up the endpoint at/ingredientsand only allowsGETrequests.
Next, you want to get all unique ingredient names from the database. You can use Prisma to do this:
prisma.ingredient.findManyasks the database for all ingredient names.select: { name: true }ensures you only get the name field.distinct: ["name"]ensures you only get each name once, even if it appears in multiple recipes.
The result from the database will look like this: [ { name: "egg" }, { name: "flour" }, { name: "milk" } ]. You want to return a simple list of strings. You can do this with map:
rows.map(r => r.name)extracts the string from each object.res.json(...)sends the list as a JSON response.
Here’s the complete endpoint:
Example Output:
If your database has eggs, flour, and milk, a GET request to /ingredients will return:
This endpoint is now ready to help users see all available ingredients.
Now, let’s add a way for users to submit reviews for recipes. This will be a POST endpoint, which means users will send data to it.
Set up the route for submitting reviews:
- This endpoint will accept
POSTrequests at/reviews.
You need to get the data the user sends and make sure it’s valid. The user should send a recipe_id and a rating (between 1 and 5). You can use the zod library for validation:
z.object({...}).safeParse(req.body)validates the incoming data.- If the data is invalid, the function returns an error message and a 400 (Bad Request) status.
Optionally, you can check if the recipe exists before saving the review:
If the data is valid, you can create a new review and save it to the database:
prisma.review.createcreates a new review record in the database.
Finally, return a message to let the user know the review was saved:
- The message confirms the review was saved.
- The status code 201 means “Created.”
Here’s the complete endpoint:
Example Input:
A user might send this JSON to /reviews:
Example Output:
If the input is invalid, for example, if the rating is 6:
The output will be:
In this lesson, you learned how to add two important features to your smart cooking API: listing all unique ingredients and allowing users to submit reviews for recipes. You saw how to define new endpoints, query the database with Prisma, validate user input using TypeScript and zod, and return clear JSON responses with Express.
Next, you’ll get a chance to practice what you’ve learned. The upcoming exercises will help you reinforce these skills by guiding you through building and testing similar endpoints on your own. This hands-on practice will ensure you’re comfortable working with Express routes, Prisma queries, and handling user data in TypeScript. Good luck!
