npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

response-kit

v2.0.0

Published

Production-grade API response utility for Node.js and Express.js with middleware support, global configuration, and async handlers

Readme

npm downloads license build

Response Kit v2.0 🚀

A production-grade, lightweight API response utility for Express.js and Node.js applications.

Version 2 brings middleware support, global configuration, async handlers, and a scalable architecture while maintaining 100% backward compatibility with v1.


✨ Why Response Kit?

Standardized API responses across your entire application
Express middleware for cleaner route handlers
Global configuration - customize once, apply everywhere
Async handler - eliminate repetitive try-catch blocks
TypeScript support with comprehensive type definitions
Zero dependencies - lightweight and fast
Production-ready - follows SOLID principles and clean architecture
Backward compatible - upgrade from v1 without breaking changes


📦 Installation

npm install response-kit

🎯 Quick Start

Method 1: Using Middleware (Recommended - v2)

const express = require('express');
const response = require('response-kit');

const app = express();

// Attach response helpers to res object
app.use(response.middleware());

app.get('/user/:id', async (req, res) => {
  const user = await getUserById(req.params.id);
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(user, 'User fetched successfully');
});

app.listen(3000);

Method 2: Direct Function Calls (v1 - Still Supported)

const response = require('response-kit');

app.get('/user/:id', async (req, res) => {
  const user = await getUserById(req.params.id);
  
  if (!user) {
    return response.notFound(res, 'User not found');
  }
  
  return response.success(res, user, 'User fetched successfully');
});

🔧 Configuration

Global Configuration

Configure once, apply everywhere:

const response = require('response-kit');

response.configure({
  successKey: 'success',        // Key for success status
  dataKey: 'data',              // Key for response data
  messageKey: 'message',        // Key for messages
  errorKey: 'errors',           // Key for error details
  includeTimestamp: true,       // Add timestamp to responses
  includeRequestId: true,       // Add request ID to responses
  includeMeta: false,           // Add request metadata
});

Example Response with Configuration:

{
  "success": true,
  "message": "User created successfully",
  "data": {
    "id": 1,
    "name": "John Doe"
  },
  "timestamp": "2024-01-15T10:30:00.000Z",
  "requestId": "1705315800000-a1b2c3d4e"
}

Custom Keys Example

response.configure({
  successKey: 'status',
  dataKey: 'result',
  messageKey: 'msg',
  errorKey: 'validationErrors',
});

Output:

{
  "status": true,
  "msg": "Success",
  "result": { "id": 1 }
}

🎭 Middleware Usage

Basic Setup

const express = require('express');
const response = require('response-kit');

const app = express();

// Apply middleware globally
app.use(response.middleware());

// Now all routes have access to response helpers via res object
app.get('/users', (req, res) => {
  res.success(users, 'Users fetched successfully');
});

Available Methods on res Object

After applying middleware, the following methods are available:

  • res.success(data, message, statusCode)
  • res.created(data, message)
  • res.badRequest(message)
  • res.unauthorized(message)
  • res.forbidden(message)
  • res.notFound(message)
  • res.conflict(message)
  • res.internalError(message)
  • res.validationError(errors, message)
  • res.paginate(data, page, limit, total)

🔄 Async Handler

Eliminate repetitive try-catch blocks in your route handlers.

Without Async Handler ❌

app.get('/users/:id', async (req, res) => {
  try {
    const user = await User.findById(req.params.id);
    return res.success(user);
  } catch (error) {
    return res.internalError(error.message);
  }
});

With Async Handler ✅

app.get('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  return res.success(user);
}));

Any errors thrown inside the handler are automatically caught and passed to Express error handling middleware.

Complete Example with Error Handler

const express = require('express');
const response = require('response-kit');

const app = express();

app.use(response.middleware());

// Routes with async handler
app.get('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(user);
}));

// Global error handler
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.internalError(err.message || 'Something went wrong');
});

app.listen(3000);

📖 API Reference

Success Responses

success(data, message, statusCode)

Send a successful response.

res.success(
  { id: 1, name: 'John' },
  'User fetched successfully',
  200
);

Response:

{
  "success": true,
  "message": "User fetched successfully",
  "data": { "id": 1, "name": "John" }
}

created(data, message)

Send a 201 Created response.

res.created(
  { id: 1, name: 'John' },
  'User created successfully'
);

Status Code: 201


Error Responses

badRequest(message)

Send a 400 Bad Request response.

res.badRequest('Invalid input data');

Status Code: 400

unauthorized(message)

Send a 401 Unauthorized response.

res.unauthorized('Invalid credentials');

Status Code: 401

forbidden(message)

Send a 403 Forbidden response.

res.forbidden('Access denied');

Status Code: 403

notFound(message)

Send a 404 Not Found response.

res.notFound('User not found');

Status Code: 404

conflict(message)

Send a 409 Conflict response.

res.conflict('Email already exists');

Status Code: 409

internalError(message)

Send a 500 Internal Server Error response.

res.internalError('Database connection failed');

Status Code: 500


Validation Errors

validationError(errors, message)

Send a 422 Unprocessable Entity response with validation errors.

res.validationError({
  email: 'Email is required',
  password: 'Password must be at least 8 characters'
}, 'Validation failed');

Response:

{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "email": "Email is required",
    "password": "Password must be at least 8 characters"
  }
}

Status Code: 422


Pagination

paginate(data, page, limit, total)

Send a paginated response.

res.paginate(users, 1, 10, 100);

Response:

{
  "success": true,
  "data": [...],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 100,
    "totalPages": 10
  }
}

🔄 Migration Guide (v1 to v2)

Good News: Zero Breaking Changes! 🎉

All v1 APIs work exactly as before. You can upgrade and adopt v2 features gradually.

Step 1: Update Package

npm install response-kit@latest

Step 2: Keep Using v1 API (Optional)

// This still works perfectly
response.success(res, data, message);
response.notFound(res, 'Not found');

Step 3: Gradually Adopt v2 Features

Add Middleware

app.use(response.middleware());

// Now you can use
res.success(data, message);
res.notFound('Not found');

Add Configuration

response.configure({
  includeTimestamp: true,
  includeRequestId: true,
});

Use Async Handler

app.get('/users', response.asyncHandler(async (req, res) => {
  const users = await User.find();
  res.success(users);
}));

Migration Examples

Before (v1):

app.get('/users/:id', async (req, res) => {
  try {
    const user = await User.findById(req.params.id);
    if (!user) {
      return response.notFound(res, 'User not found');
    }
    return response.success(res, user);
  } catch (error) {
    return response.internalError(res, error.message);
  }
});

After (v2):

app.use(response.middleware());

app.get('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  if (!user) {
    return res.notFound('User not found');
  }
  return res.success(user);
}));

💡 Complete Examples

Example 1: RESTful User API

const express = require('express');
const response = require('response-kit');

const app = express();
app.use(express.json());
app.use(response.middleware());

// Configure globally
response.configure({
  includeTimestamp: true,
  includeRequestId: true,
});

// Get all users with pagination
app.get('/users', response.asyncHandler(async (req, res) => {
  const page = parseInt(req.query.page) || 1;
  const limit = parseInt(req.query.limit) || 10;
  
  const users = await User.find()
    .skip((page - 1) * limit)
    .limit(limit);
  
  const total = await User.countDocuments();
  
  return res.paginate(users, page, limit, total);
}));

// Get user by ID
app.get('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findById(req.params.id);
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(user, 'User fetched successfully');
}));

// Create new user
app.post('/users', response.asyncHandler(async (req, res) => {
  const { email, name, password } = req.body;
  
  // Validation
  if (!email || !name || !password) {
    return res.validationError({
      email: !email ? 'Email is required' : undefined,
      name: !name ? 'Name is required' : undefined,
      password: !password ? 'Password is required' : undefined,
    });
  }
  
  // Check if user exists
  const existingUser = await User.findOne({ email });
  if (existingUser) {
    return res.conflict('User with this email already exists');
  }
  
  // Create user
  const user = await User.create({ email, name, password });
  
  return res.created(user, 'User created successfully');
}));

// Update user
app.put('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findByIdAndUpdate(
    req.params.id,
    req.body,
    { new: true }
  );
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(user, 'User updated successfully');
}));

// Delete user
app.delete('/users/:id', response.asyncHandler(async (req, res) => {
  const user = await User.findByIdAndDelete(req.params.id);
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(null, 'User deleted successfully');
}));

// Global error handler
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.internalError(err.message || 'Internal server error');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Example 2: Authentication API

const express = require('express');
const response = require('response-kit');
const jwt = require('jsonwebtoken');

const app = express();
app.use(express.json());
app.use(response.middleware());

// Login
app.post('/auth/login', response.asyncHandler(async (req, res) => {
  const { email, password } = req.body;
  
  if (!email || !password) {
    return res.badRequest('Email and password are required');
  }
  
  const user = await User.findOne({ email });
  
  if (!user || !await user.comparePassword(password)) {
    return res.unauthorized('Invalid credentials');
  }
  
  const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET);
  
  return res.success({ token, user }, 'Login successful');
}));

// Protected route
app.get('/profile', authenticateToken, response.asyncHandler(async (req, res) => {
  const user = await User.findById(req.user.id);
  
  if (!user) {
    return res.notFound('User not found');
  }
  
  return res.success(user);
}));

// Middleware
function authenticateToken(req, res, next) {
  const token = req.headers['authorization']?.split(' ')[1];
  
  if (!token) {
    return res.unauthorized('Access token required');
  }
  
  try {
    req.user = jwt.verify(token, process.env.JWT_SECRET);
    next();
  } catch (error) {
    return res.forbidden('Invalid or expired token');
  }
}

app.listen(3000);

📚 Documentation


🤝 Contributing

Contributions are welcome! Please read CONTRIBUTING.md for details.


📝 Changelog

See CHANGELOG.md for release notes.


📄 License

MIT © Piyush Yadav


🌟 Features Summary

| Feature | v1 | v2 | |---------|----|----| | Success/Error responses | ✅ | ✅ | | Pagination | ✅ | ✅ | | TypeScript support | ✅ | ✅ | | Express middleware | ❌ | ✅ | | Global configuration | ❌ | ✅ | | Async handler | ❌ | ✅ | | Request ID tracking | ❌ | ✅ | | Timestamp support | ❌ | ✅ | | Custom response keys | ❌ | ✅ | | Backward compatible | - | ✅ |


🚀 Why Upgrade to v2?

  1. Cleaner Code: Middleware reduces boilerplate
  2. Flexible Configuration: Customize response structure globally
  3. Better Error Handling: Async handler eliminates try-catch blocks
  4. Production Features: Request IDs, timestamps, metadata
  5. Modern Architecture: SOLID principles, scalable structure
  6. Zero Risk: 100% backward compatible with v1

⭐ Show Your Support

If you find this package helpful, please give it a star on GitHub!


Built with ❤️ by developers, for developers.