HTTP Response and Error Formatting for Node.js

raw JSON →
1.1.0 verified Thu Apr 23 auth: no javascript

http-response-kit is a TypeScript-first library designed for standardizing HTTP error and success responses in Node.js applications, particularly useful for RESTful APIs. It provides a comprehensive set of HTTP status codes (1xx-5xx) and convenient factory methods like `HttpError.notFound()` and `HttpResponse.ok()`. Key differentiators include full type safety, zero external dependencies, global and instance-level customization options, and support for both ESM and CommonJS module systems. Currently at version 1.1.0, the package aims for stability and consistency in API response formatting, abstracting away much of the boilerplate associated with handling HTTP statuses and response bodies.

error TypeError: (0 , http_response_kit__WEBPACK_IMPORTED_MODULE_0__.HttpError).notFound is not a function
cause This typically occurs in a CommonJS environment or incorrect bundling when trying to access `HttpError.notFound` as a property of a default import, or if the library's exports are not correctly interpreted as named exports.
fix
Ensure you are using named imports correctly: import { HttpError } from 'http-response-kit'; for ESM/TypeScript. For CommonJS, use const { HttpError } = require('http-response-kit');.
error ReferenceError: configure is not defined
cause The `configure` function was not imported or is out of scope when called.
fix
Add configure to your named imports: import { HttpError, HttpResponse, configure } from 'http-response-kit';.
error UnhandledPromiseRejectionWarning: HttpError: User not found
cause An `HttpError` was thrown in an asynchronous context (e.g., an `async` function) but was not caught by a `try...catch` block, or the global error handler is not properly set up to catch such rejections.
fix
Ensure all async route handlers and service functions that might throw HttpError are wrapped in try...catch blocks, or that your global error handling middleware in frameworks like Express correctly intercepts unhandled promise rejections.
gotcha It is crucial to implement a global error handling middleware (e.g., in Express) that uses `HttpError.fromError(err)` to catch all unhandled exceptions and convert them into standardized `HttpError` instances. Failing to do so can result in inconsistent API responses for unhandled errors, as non-`HttpError` exceptions will not be automatically formatted by the library.
fix Ensure your Express app includes a final error-handling middleware (`app.use((err, req, res, next) => { ... })`) that calls `HttpError.fromError(err)` before sending the `HttpResponse.error()`.
gotcha The `configure()` function modifies global settings for the library. Calling it multiple times with different configurations might lead to unexpected behavior if not managed carefully. It's best to call `configure()` once at your application's bootstrap phase.
fix Call `configure()` only once, ideally when your application initializes, to ensure consistent global settings throughout its lifecycle.
gotcha While `http-response-kit` supports both ESM and CommonJS, developers coming from older Node.js projects might mistakenly use `require()` syntax with default imports or try to directly `new HttpError()` without correctly importing the named exports, leading to runtime errors.
fix Always use named imports (`import { HttpError, HttpResponse } from 'http-response-kit';`) for modern TypeScript/ESM projects. For CJS, use explicit named exports: `const { HttpError } = require('http-response-kit');`.
npm install http-response-kit
yarn add http-response-kit
pnpm add http-response-kit

Demonstrates setting up a basic Express server, configuring http-response-kit, handling successful API responses, throwing and catching `HttpError` instances, and implementing a global error handling middleware for consistent API error formatting.

import express from 'express';
import { HttpError, HttpResponse, configure } from 'http-response-kit';

const app = express();

// Configure the library globally
configure({
  isDevelopment: process.env.NODE_ENV === 'development',
  includeTimestamp: true,
  // Optional: customize default messages or add global metadata
  defaultErrorMessage: 'An unexpected error occurred.',
});

// Mock database function
const findUser = async (id: string) => {
  if (id === '123') {
    return { id: 123, name: 'John Doe', email: 'john.doe@example.com' };
  }
  return null;
};

// Define a route that uses http-response-kit
app.get('/users/:id', async (req, res) => {
  try {
    const user = await findUser(req.params.id);
    if (!user) {
      // Throw an HttpError directly
      throw HttpError.notFound(`User with ID ${req.params.id} not found`);
    }
    // Format a success response
    res.status(200).json(HttpResponse.ok(user, 'User retrieved successfully'));
  } catch (err) {
    // Ensure all errors are converted to HttpError for consistent output
    const error = HttpError.fromError(err);
    // Send the formatted error response with the correct status code
    res.status(error.code).json(HttpResponse.error(error));
  }
});

// Global error handler middleware for Express
// This should be defined AFTER all your routes and other middleware.
app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {
  // Convert any unhandled error (including non-HttpErrors) into a standardized HttpError
  const error = HttpError.fromError(err);
  // Log the error in development, or less detail in production
  if (configure().isDevelopment) {
    console.error('Unhandled API Error:', error.originalError || error);
  }
  // Send the standardized error response
  res.status(error.code).json(HttpResponse.error(error));
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
  console.log(`Try: GET http://localhost:${PORT}/users/123`);
  console.log(`Try: GET http://localhost:${PORT}/users/456`);
});