/** * API Route Template * * Usage: Copy this file to create new API routes * 1. Replace TEMPLATE_NAME with your route name * 2. Implement your route handlers (GET, POST, PUT, DELETE) * 3. Add proper validation and error handling */ import { NextRequest, NextResponse } from 'next/server' import { z } from 'zod' import { authMiddleware } from '@/lib/auth-middleware' // Request validation schemas const GetRequestSchema = z.object({ // Define query parameters page: z.string().optional().default('1').transform(Number), limit: z.string().optional().default('10').transform(Number), search: z.string().optional(), }) const PostRequestSchema = z.object({ // Define request body structure name: z.string().min(1, 'Name is required'), description: z.string().optional(), tags: z.array(z.string()).optional(), }) const PutRequestSchema = z.object({ // Define update request body id: z.string().min(1, 'ID is required'), name: z.string().min(1, 'Name is required').optional(), description: z.string().optional(), }) // Type definitions type GetParams = z.infer type PostBody = z.infer type PutBody = z.infer /** * GET /api/template-route * Retrieve items with pagination and filtering */ export async function GET(request: NextRequest) { try { // Authentication check (remove if public endpoint) const user = await authMiddleware(request) if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } // Parse and validate query parameters const { searchParams } = new URL(request.url) const rawParams = Object.fromEntries(searchParams.entries()) const params = GetRequestSchema.parse(rawParams) // Implement your business logic here const { page, limit, search } = params // Example: Database query // const items = await db.collection.find({ // ...(search && { name: { $regex: search, $options: 'i' } }), // }) // .skip((page - 1) * limit) // .limit(limit) // .toArray(); // Mock response const items = [ { id: '1', name: 'Example Item 1', description: 'Description 1' }, { id: '2', name: 'Example Item 2', description: 'Description 2' }, ] return NextResponse.json({ success: true, data: { items, pagination: { page, limit, total: items.length, totalPages: Math.ceil(items.length / limit), }, }, }) } catch (error) { console.error('GET /api/template-route error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Invalid query parameters', details: error.issues }, { status: 400 } ) } return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } } /** * POST /api/template-route * Create a new item */ export async function POST(request: NextRequest) { try { // Authentication check const user = await authMiddleware(request) if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } // Parse and validate request body const rawBody = await request.json() const body = PostRequestSchema.parse(rawBody) // Implement your business logic here const { name, description, tags } = body // Example: Database insertion // const newItem = await db.collection.insertOne({ // name, // description, // tags, // createdBy: user.id, // createdAt: new Date(), // }); // Mock response const newItem = { id: 'new-item-id', name, description, tags, createdBy: user.id, createdAt: new Date().toISOString(), } return NextResponse.json( { success: true, data: newItem, }, { status: 201 } ) } catch (error) { console.error('POST /api/template-route error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Invalid request body', details: error.issues }, { status: 400 } ) } return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } } /** * PUT /api/template-route * Update an existing item */ export async function PUT(request: NextRequest) { try { // Authentication check const user = await authMiddleware(request) if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } // Parse and validate request body const rawBody = await request.json() const body = PutRequestSchema.parse(rawBody) // Implement your business logic here const { id, name, description } = body // Example: Database update // const updatedItem = await db.collection.findOneAndUpdate( // { _id: id, createdBy: user.id }, // Ensure user owns the item // { // $set: { // ...(name && { name }), // ...(description && { description }), // updatedAt: new Date(), // } // }, // { returnDocument: 'after' } // ); // if (!updatedItem.value) { // return NextResponse.json( // { error: 'Item not found or unauthorized' }, // { status: 404 } // ); // } // Mock response const updatedItem = { id, name: name || 'Existing Name', description: description || 'Existing Description', updatedAt: new Date().toISOString(), } return NextResponse.json({ success: true, data: updatedItem, }) } catch (error) { console.error('PUT /api/template-route error:', error) if (error instanceof z.ZodError) { return NextResponse.json( { error: 'Invalid request body', details: error.issues }, { status: 400 } ) } return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } } /** * DELETE /api/template-route/[id] * Delete an item */ export async function DELETE(request: NextRequest, { params }: { params: { id: string } }) { try { // Authentication check const user = await authMiddleware(request) if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } const { id } = params if (!id) { return NextResponse.json({ error: 'ID is required' }, { status: 400 }) } // Implement your business logic here // Example: Database deletion // const deletedItem = await db.collection.findOneAndDelete({ // _id: id, // createdBy: user.id, // Ensure user owns the item // }); // if (!deletedItem.value) { // return NextResponse.json( // { error: 'Item not found or unauthorized' }, // { status: 404 } // ); // } return NextResponse.json({ success: true, message: 'Item deleted successfully', }) } catch (error) { console.error('DELETE /api/template-route error:', error) return NextResponse.json({ error: 'Internal server error' }, { status: 500 }) } } /** * Common Response Types: * * Success Response: * { * success: true, * data: any, * message?: string * } * * Error Response: * { * error: string, * details?: any, * code?: string * } * * Pagination Response: * { * success: true, * data: { * items: any[], * pagination: { * page: number, * limit: number, * total: number, * totalPages: number * } * } * } */