API Response Formatter

The API Response Formatter component provides a consistent, predictable, and type-safe response structure for Express-based APIs.

It enforces a unified response contract across your entire backend, improving:

  • Client-side reliability
  • API readability
  • Error handling consistency
  • Developer experience

This component is designed to work seamlessly with:

  • Async Handler
  • ApiError
  • Centralized error middleware
  • Frontend API clients

Installation Guide

This component requires additional Servercn components.

👉 You do not need to install any Servercn components manually. Running this component installer will automatically install all required components. Manual installation is optional and only recommended if you prefer fine-grained components control

npx servercn-cli add response-formatter

The Problem It Solves

In many Express applications, responses quickly become inconsistent:

res.json(data);
res.status(201).send(user);
res.status(400).json({ error: "Invalid input" });

Basic Implementation

MVC: src/utils/api-response.ts

Feature: src/shared/utils/api-response.ts

import { STATUS_CODES, StatusCode } from "../constants/status-codes";
import type { Response } from "express";
 
type ApiResponseParams<T> = {
  success: boolean;
  message: string;
  statusCode: StatusCode;
  data?: T | null;
  errors?: unknown;
};
 
export class ApiResponse<T = unknown> {
  public readonly success: boolean;
  public readonly message: string;
  public readonly statusCode: StatusCode;
  public readonly data?: T | null;
  public readonly errors?: unknown;
 
  constructor({
    success,
    message,
    statusCode,
    data = null,
    errors
  }: ApiResponseParams<T>) {
    this.success = success;
    this.message = message;
    this.statusCode = statusCode;
    this.data = data;
    this.errors = errors;
  }
 
  send(res: Response): Response {
    return res.status(this.statusCode).json({
      success: this.success,
      message: this.message,
      statusCode: this.statusCode,
      ...(this.data !== undefined && { data: this.data }),
      ...(this.errors !== undefined && { errors: this.errors })
    });
  }
 
  static Success<T>(
    res: Response,
    message: string,
    data?: T,
    statusCode: StatusCode = STATUS_CODES.OK
  ): Response {
    return new ApiResponse<T>({
      success: true,
      message,
      data,
      statusCode
    }).send(res);
  }
 
  static ok<T>(res: Response, message = "OK", data?: T) {
    return ApiResponse.Success(res, message, data, STATUS_CODES.OK);
  }
 
  static created<T>(res: Response, message = "Created", data?: T) {
    return ApiResponse.Success(res, message, data, STATUS_CODES.CREATED);
  }
}
 
/*
 * Usage:
 * ApiResponse.ok(res, "OK", data);
 * ApiResponse.created(res, "Created", data);
 */

Usage Example

import { Request, Response } from "express";
import { ApiResponse } from "../utils/api-response";
 
export async function healthCheck(_req: Request, res: Response) {
  return ApiResponse.ok(res, "Service is healthy");
}

Response

{
  "success": true,
  "message": "Service is healthy",
  "statusCode": 200
}

File & Folder Structure

ServerCN

Select a file to view its contents

Installation

npx servercn-cli add response-formatter