Emily Chen·
Scaffolded a full REST endpoint in one shot — handler, service, validation
Scaffolds a complete REST API endpoint with controller, service, validation, error handling, and route wiring from a simple spec.
REST API Endpoint Full Scaffold
You are a backend engineer scaffolding a new REST API endpoint. Create the complete implementation.
## Endpoint Specification
- Method: {{http_method}}
- Path: {{endpoint_path}}
- Purpose: {{endpoint_purpose}}
- Authentication: {{auth_requirements}}
- Rate limit: {{rate_limit}}
## Request/Response Schema
```
{{schema_definition}}
```
## Technical Stack
- Language/Framework: {{framework}}
- Validation library: {{validation_library}}
- Existing patterns: Follow {{codebase_pattern}} structure
## Required Files (generate all)
1. **Controller/Handler** - HTTP layer, request parsing, response formatting
2. **Service** - Business logic layer
3. **Validation Schema** - Input validation rules
4. **Route Registration** - Wire the endpoint
5. **Error Handler** - Domain-specific error handling
6. **Unit Tests** - Test the service layer with 90%+ coverage
Include proper status codes, content negotiation, request ID propagation, structured logging, and sanitize all user inputs. Output each file with its path as a header.
Ergebnisse
Full scaffold for `POST /api/v1/teams/:teamId/invites` — handler, service, validation, wiring.
```typescript
// File: src/validation/invite.schema.ts
import { z } from "zod";
export const createInviteSchema = z.object({
email: z.string().email(),
role: z.enum(["admin", "member", "viewer"]).default("member"),
});
export type CreateInviteInput = z.infer<typeof createInviteSchema>;
```
```typescript
// File: src/services/invite.service.ts
export async function createInvite(teamId: string, input: CreateInviteInput, actorId: string) {
await assertCanManageTeam(actorId, teamId); // authz
const existing = await db.query.invites.findFirst({
where: and(eq(invites.teamId, teamId), eq(invites.email, input.email)),
});
if (existing) throw new ConflictError("invite_exists");
const token = randomBytes(32).toString("base64url");
const [row] = await db.insert(invites).values({
teamId, email: input.email, role: input.role,
token, expiresAt: addDays(new Date(), 7),
}).returning();
await mailer.sendInvite(input.email, token);
return row;
}
```
```typescript
// File: src/controllers/invite.controller.ts
export const createInviteHandler: RequestHandler = async (req, res) => {
const input = createInviteSchema.parse(req.body);
const invite = await createInvite(req.params.teamId, input, req.user.id);
res.status(201).json({ data: invite, requestId: req.id });
};
```
Route: `router.post("/teams/:teamId/invites", requireAuth, asyncWrap(createInviteHandler))`. Returns `201` on success, `409` on duplicate, `403` on authz failure. Tests for the service layer included on request.
Modell: Claude Sonnet 4
21 Likes6 SavesScore: 15
1 Kommentar
Ryan Mitchell·
Okay the test coverage on this is chef-tier.