Introduction: Enhancing Our Cooking API

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.

Quick Recall: Express Endpoints Refresher

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 /hello and only allows GET requests.
  • 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.

Building the Ingredients Endpoint

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.

Step 1: Define the Route

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 /ingredients and only allows GET requests.
Step 2: Query the Database

Next, you want to get all unique ingredient names from the database. You can use Prisma to do this:

  • prisma.ingredient.findMany asks 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.
Step 3: Format the Results

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.
Full Example

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.

Building the Reviews Endpoint

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.

Step 1: Define the Route

Set up the route for submitting reviews:

  • This endpoint will accept POST requests at /reviews.
Step 2: Get and Validate the Data

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:

Step 3: Save the Review

If the data is valid, you can create a new review and save it to the database:

  • prisma.review.create creates a new review record in the database.
Step 4: Return a Confirmation

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.”
Full Example

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:

Summary and Practice Preview

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!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal