import { NextApiResponse } from "next"; export type ApiResponse = ApiSuccessResponse | ApiErrorResponse; interface ApiSuccessResponse { data: T; } interface ApiErrorResponse { code: | "not_found" | "gone" | "bad_request" | "internal_server_error" | "unauthorized" | "method_not_allowed" | "not_authenticated" | "forbidden"; message: string; details: { [key: string]: string | string[] | number | number[] | boolean | boolean[]; }; } export type CustomNextApiResponse = NextApiResponse; const corsHeaders = { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }; const goneResponse = ( message: string, details?: { [key: string]: string }, cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "gone", message, details: details || {}, } as ApiErrorResponse, { status: 410, headers, } ); }; const badRequestResponse = ( message: string, details?: { [key: string]: string }, cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "bad_request", message, details: details || {}, } as ApiErrorResponse, { status: 400, headers, } ); }; const methodNotAllowedResponse = ( res: CustomNextApiResponse, allowedMethods: string[], cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "method_not_allowed", message: `The HTTP ${res.req?.method} method is not supported by this route.`, details: { allowed_methods: allowedMethods, }, } as ApiErrorResponse, { status: 405, headers, } ); }; const notFoundResponse = ( resourceType: string, resourceId: string | null, cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "not_found", message: `${resourceType} not found`, details: { resource_id: resourceId, resource_type: resourceType, }, } as ApiErrorResponse, { status: 404, headers, } ); }; const notAuthenticatedResponse = (cors: boolean = false, cache: string = "private, no-store") => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "not_authenticated", message: "Not authenticated", details: { "x-Api-Key": "Header not provided or API Key invalid", }, } as ApiErrorResponse, { status: 401, headers, } ); }; const unauthorizedResponse = (cors: boolean = false, cache: string = "private, no-store") => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "unauthorized", message: "You are not authorized to access this resource", details: {}, } as ApiErrorResponse, { status: 401, headers, } ); }; const forbiddenResponse = ( message: string, cors: boolean = false, details: ApiErrorResponse["details"] = {}, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "forbidden", message, details, } as ApiErrorResponse, { status: 403, headers, } ); }; const successResponse = (data: Object, cors: boolean = false, cache: string = "private, no-store") => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { data, } as ApiSuccessResponse, { status: 200, headers, } ); }; const internalServerErrorResponse = ( message: string, cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "internal_server_error", message, details: {}, } as ApiErrorResponse, { status: 500, headers, } ); }; const tooManyRequestsResponse = ( message: string, cors: boolean = false, cache: string = "private, no-store" ) => { const headers = { ...(cors && corsHeaders), "Cache-Control": cache, }; return Response.json( { code: "internal_server_error", message, details: {}, } as ApiErrorResponse, { status: 429, headers, } ); }; export const responses = { goneResponse, badRequestResponse, internalServerErrorResponse, methodNotAllowedResponse, notAuthenticatedResponse, unauthorizedResponse, notFoundResponse, successResponse, tooManyRequestsResponse, forbiddenResponse, };