Skip to main content
Ryan Mitchell·

Full CRUD for our invoices resource - validation, cursor pagination, optimistic locking, done

Generates a complete CRUD REST API for any resource with validation, pagination, filtering, sorting, and authorization.

Full CRUD API Generator with Validation

You are a backend engineer generating a complete CRUD API for a resource. Build all layers. ## Resource Spec - Resource name: {{resource_name}} - Fields: ``` {{field_definitions}} ``` - Language/Framework: {{framework}} - Database: {{database}} - ORM/Query builder: {{orm}} ## CRUD Requirements Generate complete implementations for: ### CREATE (POST /{{resource_name}}s) - Request validation (type, format, range, uniqueness) - Business rule validation - Transaction-wrapped creation - Return 201 with created resource - Location header ### READ LIST (GET /{{resource_name}}s) - Pagination (cursor-based or offset with limit) - Filtering (eq, ne, gt, lt, contains, in, date range) - Sorting (multi-column, asc/desc) - Field selection (sparse fieldsets) - Search (full-text if applicable) - Return 200 with paginated result envelope ### READ ONE (GET /{{resource_name}}s/:id) - 404 handling for missing resources - Return 200 with resource ### UPDATE (PATCH /{{resource_name}}s/:id) - Partial update support - Optimistic locking (ETag/If-Match or version field) - Validation same as create - Return 200 with updated resource ### DELETE (DELETE /{{resource_name}}s/:id) - Soft delete (deleted_at) or hard delete based on spec - Cascade behavior documentation - Return 204 No Content ## Additional Files 1. **Validation Schema** - Zod/Joi/yup/class-validator schema 2. **DTOs** - Request/response types 3. **Repository** - Data access layer 4. **Service** - Business logic 5. **Controller/Routes** - HTTP handling 6. **Tests** - All CRUD operations with edge cases 7. **OpenAPI Spec** - YAML/JSON spec for these endpoints Follow REST conventions. Use proper HTTP status codes. Handle 400, 401, 403, 404, 409, 422, 500 appropriately.

Ergebnisse

Full CRUD for the `invoice` resource — Express + TypeScript + Drizzle on Postgres. Validation, cursor pagination, optimistic locking. ```typescript // validation.ts export const createInvoice = z.object({ customerId: z.string().uuid(), amountCents: z.number().int().positive(), dueDate: z.coerce.date(), }); // routes.ts router.post("/invoices", requireAuth, async (req, res) => { const input = createInvoice.parse(req.body); const [row] = await db.insert(invoices) .values({ ...input, ownerId: req.user.id }).returning(); res.status(201).location(`/invoices/${row.id}`).json({ data: row }); }); router.get("/invoices", requireAuth, async (req, res) => { const { cursor, status, sort = "createdAt:desc" } = req.query; const rows = await listInvoices({ ownerId: req.user.id, cursor, status, sort }); res.json({ data: rows, nextCursor: rows.at(-1)?.id ?? null }); }); router.patch("/invoices/:id", requireAuth, async (req, res) => { const result = await db.update(invoices) .set({ ...req.body, version: sql`version + 1` }) .where(and( eq(invoices.id, req.params.id), eq(invoices.version, Number(req.headers["if-match"])), // optimistic lock )).returning(); if (!result.length) return res.status(409).json({ error: "version_conflict" }); res.json({ data: result[0] }); }); ``` **Status codes:** 201 create (+ `Location`), 200 list/read/update, 204 delete (soft, sets `deletedAt`), 404 missing, 409 stale `If-Match`, 422 validation. List supports `eq/in/date-range` filters and multi-column sort. OpenAPI YAML for all five routes is generated alongside.

Modell: Claude Sonnet 4

5 Likes2 SavesScore: 4