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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@geekmidas/errors

v0.0.1

Published

Type-safe HTTP error classes with full TypeScript support, providing structured error handling for REST APIs and HTTP-based applications.

Downloads

255

Readme

@geekmidas/errors

Type-safe HTTP error classes with full TypeScript support, providing structured error handling for REST APIs and HTTP-based applications.

Features

  • Type-Safe Errors: Full TypeScript support with proper error hierarchies
  • HTTP Status Codes: Pre-built error classes for all common HTTP errors
  • Structured Error Details: Include additional context and debugging information
  • Error Factories: Convenient factory functions for creating errors
  • Type Guards: Runtime type checking for error instances
  • JSON Serialization: Built-in support for error serialization
  • Error Wrapping: Wrap unknown errors into HTTP errors
  • Cause Chaining: ES2022 error cause support for error chains

Installation

pnpm add @geekmidas/errors

Quick Start

Basic Usage

import {
  BadRequestError,
  NotFoundError,
  UnauthorizedError,
  InternalServerError
} from '@geekmidas/errors';

// Throw specific error types
throw new NotFoundError('User not found');
throw new BadRequestError('Invalid email format');
throw new UnauthorizedError('Invalid token');
throw new InternalServerError('Database connection failed');

With Error Details

import { BadRequestError, NotFoundError } from '@geekmidas/errors';

// Include additional context
throw new NotFoundError('User not found', { userId: '123' });

throw new BadRequestError('Validation failed', {
  field: 'email',
  value: 'invalid-email',
  message: 'Must be a valid email address'
});

Available Error Classes

Client Errors (4xx)

import {
  BadRequestError,           // 400
  UnauthorizedError,        // 401
  ForbiddenError,           // 403
  NotFoundError,            // 404
  MethodNotAllowedError,    // 405
  ConflictError,            // 409
  UnprocessableEntityError, // 422
  TooManyRequestsError      // 429
} from '@geekmidas/errors';

// 400 Bad Request
throw new BadRequestError('Invalid input');

// 401 Unauthorized
throw new UnauthorizedError('Authentication required');

// 403 Forbidden
throw new ForbiddenError('Insufficient permissions', {
  required: 'admin',
  current: 'user'
});

// 404 Not Found
throw new NotFoundError('Resource not found');

// 405 Method Not Allowed
throw new MethodNotAllowedError('DELETE not supported', ['GET', 'POST', 'PUT']);

// 409 Conflict
throw new ConflictError('Email already exists', {
  email: '[email protected]'
});

// 422 Unprocessable Entity
throw new UnprocessableEntityError('Validation failed', {
  email: 'Invalid email format',
  age: 'Must be 18 or older'
});

// 429 Too Many Requests
throw new TooManyRequestsError('Rate limit exceeded', 60); // retry after 60 seconds

Server Errors (5xx)

import {
  InternalServerError, // 500
  NotImplementedError, // 501
  BadGatewayError,     // 502
  ServiceUnavailableError, // 503
  GatewayTimeoutError  // 504
} from '@geekmidas/errors';

// 500 Internal Server Error
throw new InternalServerError('Database connection failed');

// 501 Not Implemented
throw new NotImplementedError('Feature not yet implemented');

// 502 Bad Gateway
throw new BadGatewayError('Upstream server error');

// 503 Service Unavailable
throw new ServiceUnavailableError('Maintenance in progress', 300); // retry after 5 minutes

// 504 Gateway Timeout
throw new GatewayTimeoutError('Upstream server timeout');

Error Factories

Use convenient factory functions for creating errors:

import { createError } from '@geekmidas/errors';

// Short, descriptive method names
throw createError.badRequest('Invalid input');
throw createError.notFound('User not found');
throw createError.unauthorized('Invalid token');
throw createError.forbidden('Access denied');
throw createError.conflict('Resource already exists');
throw createError.internalServerError('Something went wrong');

// With details
throw createError.notFound('User not found', { userId: '123' });
throw createError.badRequest('Validation failed', {
  errors: ['Invalid email', 'Password too short']
});

Generic Error Factory

Create errors dynamically with type-safe options:

import { createHttpError } from '@geekmidas/errors';

// TypeScript knows which options are valid for each status code
throw createHttpError(404, 'Not found');
throw createHttpError(429, 'Rate limited', { retryAfter: 60 });
throw createHttpError(422, 'Validation failed', {
  validationErrors: {
    email: 'Invalid format',
    age: 'Must be 18+'
  }
});

Type Guards

Check error types at runtime:

import {
  isHttpError,
  isClientError,
  isServerError,
  NotFoundError
} from '@geekmidas/errors';

try {
  // some code
} catch (error) {
  if (isHttpError(error)) {
    console.log(`HTTP ${error.statusCode}: ${error.message}`);
    console.log('Details:', error.details);
  }

  if (isClientError(error)) {
    // 4xx errors - client's fault
    console.log('Client error:', error.message);
  }

  if (isServerError(error)) {
    // 5xx errors - server's fault
    console.error('Server error:', error.message);
    // Alert monitoring system
  }

  if (error instanceof NotFoundError) {
    // Specific error type
    console.log('Resource not found');
  }
}

Error Wrapping

Wrap unknown errors into HTTP errors:

import { wrapError } from '@geekmidas/errors';

try {
  await someOperation();
} catch (error) {
  // Wrap unknown error as 500
  throw wrapError(error);

  // Or wrap with specific status and message
  throw wrapError(error, 503, 'Service temporarily unavailable');
}

Error Serialization

Serialize errors to JSON:

import { NotFoundError } from '@geekmidas/errors';

const error = new NotFoundError('User not found', { userId: '123' });

// Get JSON representation
const json = error.toJSON();
// {
//   name: 'NotFoundError',
//   message: 'User not found',
//   statusCode: 404,
//   statusMessage: 'Not Found',
//   details: { userId: '123' },
//   stack: '...'
// }

// Get error body for HTTP response
const body = error.body;
// JSON string: '{"message":"User not found","details":{"userId":"123"}}'

Error Cause Chaining

Chain errors using ES2022 error cause:

import { InternalServerError } from '@geekmidas/errors';

try {
  await database.connect();
} catch (originalError) {
  throw new InternalServerError('Failed to connect to database', {
    cause: originalError,
    details: { host: 'localhost', port: 5432 }
  });
}

Express Middleware

Handle errors in Express applications:

import { isHttpError } from '@geekmidas/errors';
import type { Request, Response, NextFunction } from 'express';

function errorHandler(
  error: unknown,
  req: Request,
  res: Response,
  next: NextFunction
) {
  if (isHttpError(error)) {
    res.status(error.statusCode).json({
      error: {
        message: error.message,
        code: error.code,
        details: error.details
      }
    });
  } else {
    // Unknown error
    console.error('Unexpected error:', error);
    res.status(500).json({
      error: {
        message: 'Internal Server Error'
      }
    });
  }
}

// Use in Express app
app.use(errorHandler);

Hono Middleware

Handle errors in Hono applications:

import { Hono } from 'hono';
import { isHttpError } from '@geekmidas/errors';

const app = new Hono();

app.onError((error, c) => {
  if (isHttpError(error)) {
    return c.json(
      {
        error: {
          message: error.message,
          code: error.code,
          details: error.details
        }
      },
      error.statusCode
    );
  }

  console.error('Unexpected error:', error);
  return c.json(
    { error: { message: 'Internal Server Error' } },
    500
  );
});

Custom Error Classes

Extend base classes for custom errors:

import { HttpError } from '@geekmidas/errors';

export class CustomBusinessError extends HttpError {
  constructor(message?: string, details?: any) {
    super(400, message, { details, code: 'BUSINESS_RULE_VIOLATION' });
  }
}

// Usage
throw new CustomBusinessError('Cannot delete user with active orders', {
  userId: '123',
  activeOrders: 5
});

Error Context

Add context to errors for better debugging:

import { NotFoundError } from '@geekmidas/errors';

function getUserById(id: string) {
  const user = database.findUser(id);

  if (!user) {
    throw new NotFoundError('User not found', {
      userId: id,
      requestId: req.headers['x-request-id'],
      timestamp: new Date().toISOString(),
      source: 'getUserById'
    });
  }

  return user;
}

HTTP Status Codes

Use the HttpStatusCode enum for type-safe status codes:

import { HttpStatusCode } from '@geekmidas/errors';

// Success
HttpStatusCode.OK                 // 200
HttpStatusCode.CREATED            // 201
HttpStatusCode.NO_CONTENT         // 204

// Redirection
HttpStatusCode.MOVED_PERMANENTLY  // 301
HttpStatusCode.NOT_MODIFIED       // 304

// Client Errors
HttpStatusCode.BAD_REQUEST        // 400
HttpStatusCode.UNAUTHORIZED       // 401
HttpStatusCode.FORBIDDEN          // 403
HttpStatusCode.NOT_FOUND          // 404
HttpStatusCode.CONFLICT           // 409
HttpStatusCode.UNPROCESSABLE_ENTITY // 422
HttpStatusCode.TOO_MANY_REQUESTS  // 429

// Server Errors
HttpStatusCode.INTERNAL_SERVER_ERROR // 500
HttpStatusCode.SERVICE_UNAVAILABLE   // 503

Best Practices

1. Use Specific Error Classes

// ❌ Don't use generic Error
throw new Error('User not found');

// ✅ Use specific HTTP error
throw new NotFoundError('User not found', { userId: '123' });

2. Include Helpful Details

// ❌ Minimal information
throw new BadRequestError('Invalid input');

// ✅ Include context
throw new BadRequestError('Invalid email format', {
  field: 'email',
  value: userInput,
  expectedFormat: '[email protected]'
});

3. Use Type Guards

// ❌ Assume error type
catch (error: any) {
  console.log(error.statusCode); // Unsafe
}

// ✅ Check error type
catch (error) {
  if (isHttpError(error)) {
    console.log(error.statusCode); // Safe
  }
}

4. Chain Errors

// ✅ Preserve original error context
try {
  await database.query();
} catch (originalError) {
  throw new InternalServerError('Database query failed', {
    cause: originalError,
    query: 'SELECT * FROM users'
  });
}

TypeScript Types

import type {
  HttpError,
  HttpErrorOptions,
  HttpErrorConstructor
} from '@geekmidas/errors';

// Options for creating errors
interface HttpErrorOptions {
  statusMessage?: string;
  details?: any;
  code?: string;
  cause?: Error;
}

// Constructor type for factory patterns
type HttpErrorConstructor = new (
  message?: string,
  options?: HttpErrorOptions
) => HttpError;

Related Packages

License

MIT