Nobody has started this yet — be first.
Business impact
Recipe authors constantly want to start a new recipe from an existing one -- a "Chicken Stir Fry" variant that swaps the protein, a smaller/larger batch with tweaked steps, a seasonal remix. Today the only way to do that through this API is to GET the original, hand-copy every field (including every ingredient and every step) into a new POST /recipes body, and resubmit. That's tedious and error-prone by hand, and it means any client wanting a "duplicate this recipe" button has to reimplement the copy logic itself instead of the server owning it. A one-call duplicate endpoint is a small addition with an outsized quality-of-life payoff for anyone actually authoring content through this API.
Problem
POST /recipes/:id/duplicate is registered as a stub in src/routes/recipes.js (see the bottom of the file, right before module.exports). It compiles and the route exists, but its handler unconditionally throws -- hitting it always returns a 500 with a generic "Internal server error" body, regardless of :id.
Current behavior
POST /recipes/1/duplicate returns 500 with a generic "Internal server error" body for every :id, including recipes that exist.
Expected behavior
POST /recipes/:id/duplicate should look up the recipe at :id (404 if it doesn't exist, reusing the existing findRecipeOr404 helper), create a new recipe row with the same title, description, cookingTimeMinutes, and servings as the original, create new Ingredient and Step rows attached to the new recipe's id copying every field from the original's ingredients/steps (never reusing the original rows' ids or recipeId), never modify the original recipe or its ingredients/steps in any way, and return 201 with the newly created recipe (same shape as POST /recipes's response).
Steps to reproduce
cd nodejs/recipe_api npm run dev # or: docker compose up
curl -X POST http://localhost:3001/recipes/1/duplicate
Why this matters
This is architecturally the same shape as POST /recipes (a nested create of a recipe plus its ingredients and steps in one transaction) -- except the source data comes from an existing DB row instead of the request body. The natural trap is copying the original ingredient/step objects wholesale into the nested create, id/recipeId fields and all -- Prisma's nested create needs plain data (name/quantity/unit, stepNumber/instruction), not rows that already carry a foreign key pointing at a different recipe.
Suggested approach
Start from findRecipeOr404 (already imported/available in this file) to fetch the source recipe with its ingredients/steps included. Then look at how POST /recipes's handler builds its prisma.recipe.create({ data: { ..., ingredients: { create: ingredients }, steps: { create: steps } } }) call -- you need the same shape, but the ingredients/steps arrays come from the fetched recipe's relations (mapped down to just the fields a nested create accepts) instead of req.body.
Acceptance criteria
Verification
npx jest --config practice-tickets/jest.config.js practice-tickets/tests/06-duplicate-endpoint-missing.test.js
Hints (0/2)
Try it without hints first — the reading is the exercise.
Working on this ticket
Work on a branch named for the ticket — that's what you'll submit.
Branch off your fork
$git checkout -b feat/duplicate-endpointFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/duplicate-endpointSubmit it below
Paste your fork URL and the branch name, with a short write-up of the root cause.
Questions
Ask about anything unclear in the ticket — the maintainer and anyone who has solved it can answer. Please don't post full solutions.
Sign in to ask a question or reply.
Sign indocker-entrypoint.shnpx prisma migrate deploydocker compose up --builddocker compose down -vWithout Docker: npm install, copy .env.example to .env and point DATABASE_URL at a local PostgreSQL instance, then npm run prisma:migrate:dev and npm run dev (nodemon, port 3001) or npm start.
The project's own suite (tests/recipes.test.js) runs against a real Postgres test database, not a mock -- create one, copy .env.example to .env.test and point it at that database, then run:
npm test
Work the tickets in practice-tickets/tickets/ (01 through 07); each names one Jest test in practice-tickets/tests/, run against the same real test database via practice-tickets/jest.config.js:
npx jest --config practice-tickets/jest.config.js practice-tickets/tests/01-max-cooking-time-boundary.test.js # a single ticket
./practice-tickets/run.sh # all 7, clean pass/fail summary
Fixing tickets 02 and 04 also turns two tests in the project's own npm test suite green again -- they break as a direct, expected side effect of those bugs touching shared route code the existing suite also exercises. That's expected, not a mistake in the scaffolding.
Level 2
Implement a feature
Extend the system within its own patterns.