Nobody has started this yet — be first.
Business impact
Right now every GET /recipes response comes back sorted by id -- i.e. by insertion order -- no matter what the caller wants. A frontend that wants to show "quickest recipes first" or "newest recipes first" currently has to fetch everything and sort client-side, which defeats the purpose of filtering/paginating on the server and means every client re-implements sorting logic the API should own. It's a small gap, but it's the kind of missing, obviously-expected capability that makes an API feel unfinished to anyone integrating against it.
Problem
The GET / handler in src/routes/recipes.js hardcodes orderBy: { id: 'asc' } on its prisma.recipe.findMany call. There is no sortBy or order query parameter -- any such param is silently ignored.
Current behavior
GET /recipes?sortBy=cookingTimeMinutes&order=desc still returns recipes ordered by id ascending -- the sortBy and order query parameters have no effect on the response.
Expected behavior
GET /recipes?sortBy=cookingTimeMinutes&order=desc should return recipes ordered by cookingTimeMinutes descending. sortBy should accept one of id, cookingTimeMinutes, servings, createdAt (rejecting anything else with a 400), order should accept asc or desc defaulting to asc if omitted, and no sortBy at all should keep today's behavior (orderBy: { id: 'asc' }) so this is backwards compatible for existing callers.
Steps to reproduce
cd nodejs/recipe_api npm run dev # or: docker compose up
curl "http://localhost:3001/recipes?sortBy=cookingTimeMinutes&order=desc"
Why this matters
The tempting shortcut here is orderBy: { [req.query.sortBy]: req.query.order } built directly from user input. Resist it: an unrecognized or malicious sortBy value would either throw an opaque Prisma error (leaking as an unhandled 500) or, depending on how Prisma validates it, silently produce no ordering guarantee at all. A hardcoded allow-list of sortable columns (mirroring how maxCookingTime's value is validated before use) keeps this safe and gives a clean 400 for bad input instead.
Suggested approach
Look at how maxCookingTime is validated in the same handler -- that's the shape to follow: validate sortBy against an allow-list and order against ['asc', 'desc'] before building the orderBy object, throwing ValidationError (already imported in this file) on anything that doesn't match.
Acceptance criteria
Verification
npx jest --config practice-tickets/jest.config.js practice-tickets/tests/05-sorting-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/sortingFix it and commit
Meet every acceptance criterion, and add a test that would have caught this.
Push the branch
$git push -u origin feat/sortingSubmit 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.