Validating Task Data with a Shared Helper
Welcome: From “It Works” to “It’s Safe to Use”
Welcome back. In the previous lesson, you used Codex to design the Task core: a shared Task model, an in-memory tasks array, and a service layer that knows how to create, read, update, and delete tasks. Your API can now do real work—but so far it mostly assumes that incoming JSON is correct.
In this lesson, you’ll upgrade your Task Manager API from “accept anything and hope” to “trust but verify.” You’ll:
- Build a central task payload validator in
src/lib/validateTaskPayload.ts - Plug that validator into
updateTaskByIdinsrc/lib/services/taskService.ts - Wire validation into PUT and PATCH for
src/app/api/tasks/[id]/route.ts, returning proper HTTP status codes
You’ll continue to rely on Codex for implementation, but now your prompts will describe more nuanced rules: allowed fields, required fields, strict types, and how to propagate errors back to the client.
What We’re Building and Why It Matters
So far, your API can:
- Store tasks in memory
- Expose
/api/tasksand/api/tasks/[id]routes - Perform basic CRUD via the service layer
What it does not do yet is enforce the rules of your domain. Examples:
- A client could send
"completed": "yes"instead of a boolean. - A task update could include random fields like
"hack": "oops". - A PUT could omit required fields entirely.
Without validation, bad data sneaks into your in-memory store and everything built on top becomes fragile.
This lesson introduces a clear separation of concerns:
validateTaskPayloadchecks if incoming data is shaped correctly.taskService.updateTaskByIddecides whether to mutate state based on validator results.- The
/api/tasks/[id]route translates service results into HTTP responses:200,400,404,204.
Once this pipeline is in place, every future feature you add (logging, persistence, UI) can assume the data is clean.
How We’ll Use Codex in This Lesson
You’ll use Codex in three focused ways:
-
To implement the reusable validator
- One file:
src/lib/validateTaskPayload.ts - Well-defined function:
validateTaskPayload(payload: any, partial = false): string[] - Return array of human-readable error messages
- One file:
-
To integrate validation into the service layer
- One function:
updateTaskByIdinsrc/lib/services/taskService.ts - Call
validateTaskPayloadand decide whether to update or return an error object
- One function:
-
To enforce validation in PUT/PATCH routes
- File:
src/app/api/tasks/[id]/route.ts - Handlers use
updateTaskByIdand map{ error } / { task }to HTTP status codes
- File:
Across all three, your prompts should:
- Restrict Codex to one file at a time
- Describe allowed fields, required fields, and type expectations clearly
- Explain how to treat partial updates vs full replacements
- Ask Codex to show the full updated file content
